1. Quick Start
Mall is a full-featured e-commerce platform built on Spring Boot, providing both a back-office admin system and a customer-facing shopping portal as REST APIs. It covers product management, order processing, promotions, member management, and full-text product search.
Key features:
- Complete product lifecycle management (categories, brands, attributes, SKUs)
- Shopping cart with promotion calculation (ladders, full-reduction, coupons)
- Order placement with automatic timeout cancellation via RabbitMQ
- Alipay payment integration (desktop, mobile, async notification)
- Elasticsearch-powered product search with aggregation
- JWT-based stateless authentication with dynamic URL-level authorization
- MinIO and Aliyun OSS file storage
- Swagger UI auto-generated API documentation
Prerequisites:
- JDK 8+
- Maven 3.x
- MySQL 5.7+, Redis 7+, MongoDB 4+, RabbitMQ 3.9+, Elasticsearch 7.17.x
Quickest path to running:
# Start infrastructure services
docker compose -f document/docker/docker-compose-env.yml up -d
# Import the database schema
mysql -u root -proot < document/sql/mall.sql
# Build all modules
mvn clean package -DskipTests
# Run the admin backend
java -jar mall-admin/target/mall-admin-1.0-SNAPSHOT.jar --spring.profiles.active=dev
The admin API is now accessible at http://localhost:8080. Swagger UI is at http://localhost:8080/swagger-ui/.
Tip
Use the included Postman collections (
document/postman/) for quick API exploration. Importmall-admin.postman_collection.jsonandmall-portal.postman_collection.jsoninto Postman.
What to try next:
- Log in via
POST /admin/loginwith{"username": "admin", "password": "123456"} - Browse products via
GET /product/list - Start the portal module for the customer-facing API on port 8085
2. Installation
System Requirements
| Component | Minimum Version | Purpose |
|---|---|---|
| JDK | 8 | Runtime |
| Maven | 3.x | Build |
| MySQL | 5.7 | Primary database |
| Redis | 7 | Caching, session |
| MongoDB | 4 | Member browsing history, collections |
| RabbitMQ | 3.9 | Order timeout cancellation |
| Elasticsearch | 7.17.x | Product search |
| MinIO | Latest | Object storage (product images) |
Infrastructure Setup with Docker Compose
The recommended approach uses the provided Docker Compose file to run all infrastructure:
docker compose -f document/docker/docker-compose-env.yml up -d
This starts:
| Service | Port | Purpose |
|---|---|---|
| MySQL | 3306 | Database (root password: root) |
| Redis | 6379 | Cache with AOF persistence |
| Nginx | 80 | Static assets / frontend proxy |
| RabbitMQ | 5672 / 15672 | Message queue / management UI |
| Elasticsearch | 9200 / 9300 | Search engine |
| Logstash | 4560-4563 | Log collection |
| Kibana | 5601 | Log visualization |
| MongoDB | 27017 | Document store |
| MinIO | 9090 / 9001 | Object storage (API / console) |
Important
After starting MySQL, import the database schema before running any application module:
mysql -u root -proot < document/sql/mall.sqlThe SQL file creates the
malldatabase with all required tables (~70 tables).
Building the Project
mvn clean package -DskipTests
This produces executable JARs in each module's target/ directory.
Running Application Modules
Start modules in this order (admin is independent; portal requires RabbitMQ and MongoDB; search requires Elasticsearch):
# Admin back-office API (port 8080)
java -jar mall-admin/target/mall-admin-1.0-SNAPSHOT.jar --spring.profiles.active=dev
# Portal customer API (port 8085)
java -jar mall-portal/target/mall-portal-1.0-SNAPSHOT.jar --spring.profiles.active=dev
# Search service (port 8081)
java -jar mall-search/target/mall-search-1.0-SNAPSHOT.jar --spring.profiles.active=dev
Docker Deployment (Production)
Build Docker images via Maven:
mvn clean package -DskipTests -Pdocker
Or use the provided deployment scripts:
# Deploy mall-admin container
bash document/sh/mall-admin.sh
# Deploy mall-portal container
bash document/sh/mall-portal.sh
# Deploy mall-search container
bash document/sh/mall-search.sh
Warning
The deployment scripts use
--linkfor container networking (legacy Docker feature). They also hard-delete dangling images. Ensure your container names match:mysql,redis,mongo,rabbitmq,elasticsearch.
Post-Installation Verification
# Check admin API health
curl http://localhost:8080/actuator/health
{"status":"UP"}
Access Swagger UI:
- Admin:
http://localhost:8080/swagger-ui/ - Portal:
http://localhost:8085/swagger-ui/ - Search:
http://localhost:8081/swagger-ui/
3. Configuration
Mall uses Spring Boot profiles for environment-specific configuration. Each module has:
application.yml— shared settingsapplication-dev.yml— development overridesapplication-prod.yml— production overrides
Activate a profile at startup:
java -jar mall-admin.jar --spring.profiles.active=prod
Key Configuration Areas
| Setting | Location | Purpose |
|---|---|---|
| Database | spring.datasource.* |
MySQL connection (Druid pool) |
| Redis | spring.redis.* |
Cache host/port |
| MongoDB | spring.data.mongodb.* |
Member data store |
| RabbitMQ | spring.rabbitmq.* |
Message broker |
| Elasticsearch | spring.elasticsearch.* |
Search cluster |
| JWT | jwt.secret, jwt.expiration, jwt.tokenHead |
Auth token config |
| Security whitelist | secure.ignored.urls |
Paths that skip authentication |
| Aliyun OSS | aliyun.oss.* |
Object storage credentials |
| MinIO | minio.* |
MinIO endpoint and credentials |
| Alipay | alipay.* |
Payment gateway config |
| Swagger | spring.mvc.pathmatch.matching-strategy |
Must be ant_path_matcher |
Tip
The
secure.ignored.urlslist controls which endpoints bypass JWT auth. In development, Swagger paths (/swagger-ui/**,/v2/api-docs,/swagger-resources/**) are whitelisted here.
For the full configuration reference (every key, every module), see the Admin Guide.
4. Core Usage
Mall exposes three REST API services. All responses use a standard envelope:
{
"code": 200,
"message": "操作成功",
"data": { }
}
| Code | Meaning |
|---|---|
200 |
Success |
401 |
Not logged in / token expired |
403 |
Insufficient permissions |
404 |
Validation failed |
500 |
Operation failed |
Authentication
All protected endpoints require a JWT token in the Authorization header:
Authorization: Bearer <token>
Admin login:
curl -X POST http://localhost:8080/admin/login \
-H "Content-Type: application/json" \
-d '{"username": "admin", "password": "123456"}'
{
"code": 200,
"message": "操作成功",
"data": {
"token": "eyJhbGciOiJIUzUxMiJ9...",
"tokenHead": "Bearer "
}
}
Member login (portal):
curl -X POST http://localhost:8085/sso/login \
-d "username=test&password=123"
Token refresh:
curl http://localhost:8080/admin/token/refresh \
-H "Authorization: Bearer <current-token>"
Note
Tokens have a configurable expiration (default varies by environment). The refresh endpoint re-issues a token only if the current one was issued more than 30 minutes ago — calling it within that window returns the same token.
Paginated Responses
List endpoints return paginated data:
{
"code": 200,
"data": {
"pageNum": 1,
"pageSize": 5,
"totalPage": 10,
"total": 48,
"list": [...]
}
}
Use pageNum and pageSize query parameters to control pagination.
4.1 Product Management (Admin)
| Endpoint | Method | Description |
|---|---|---|
/product/list |
GET | List products (paginated, filterable) |
/product/create |
POST | Create a new product |
/product/update/{id} |
POST | Update product details |
/product/update/deleteStatus |
POST | Batch soft-delete products |
/brand/listAll |
GET | List all brands |
/brand/list |
GET | Paginated brand list |
/brand/create |
POST | Create a brand |
/productCategory/list/withChildren |
GET | Category tree |
/productCategory/list/{parentId} |
GET | Subcategories |
/productAttribute/list/{cid} |
GET | Attributes for a category |
/skuStock/update/{pid} |
POST | Update SKU stock |
4.2 Order Management (Admin)
| Endpoint | Method | Description |
|---|---|---|
/order/list |
GET | List orders with filters |
/order/{id} |
GET | Order detail |
/order/update/delivery |
POST | Batch ship orders |
/order/update/close |
POST | Close orders |
/order/update/moneyInfo |
POST | Modify order amounts |
/order/update/receiverInfo |
POST | Update shipping address |
/returnApply/list |
GET | Return applications |
/returnApply/update/status |
POST | Process return |
/orderSetting/update/{id} |
POST | Update order settings |
4.3 Promotions (Admin)
| Endpoint | Method | Description |
|---|---|---|
/coupon/add |
POST | Create coupon |
/coupon/update/{id} |
POST | Update coupon |
/coupon/delete/{id} |
POST | Delete coupon |
/coupon/list |
GET | List coupons |
/flash/create |
POST | Create flash sale event |
/flash/update/{id} |
POST | Update flash sale |
/flashSession/list |
GET | List flash sale sessions |
/flashProductRelation/create |
POST | Add product to flash sale |
/home/advertise/list |
GET | Homepage ads |
/home/brand/list |
GET | Homepage brand recommendations |
/home/newProduct/list |
GET | Homepage new arrivals |
/home/recommendProduct/list |
GET | Homepage recommended products |
4.4 User & Permission Management (Admin)
| Endpoint | Method | Description |
|---|---|---|
/admin/list |
GET | List admin users |
/admin/register |
POST | Register new admin |
/admin/update/{id} |
POST | Update admin user |
/admin/updatePassword |
POST | Change password |
/role/list |
GET | List roles |
/role/create |
POST | Create role |
/role/allocResource |
POST | Assign resources to role |
/role/allocMenu |
POST | Assign menus to role |
/resource/list |
GET | List resources |
/resource/create |
POST | Create resource |
/menu/treeList |
GET | Menu tree |
4.5 Shopping (Portal)
| Endpoint | Method | Description |
|---|---|---|
/cart/add |
POST | Add item to cart |
/cart/list |
GET | Get cart items |
/cart/list/promotion |
GET | Cart with promotion calculations |
/cart/update/quantity |
GET | Update item quantity |
/cart/update/attr |
POST | Change item specifications |
/cart/delete |
POST | Remove items from cart |
/cart/clear |
POST | Empty cart |
/cart/getProduct/{productId} |
GET | Get product specs for re-selection |
4.6 Orders (Portal)
| Endpoint | Method | Description |
|---|---|---|
/order/confirmOrder |
POST | Generate order confirmation |
/order/generateOrder |
POST | Place order |
/order/paySuccess |
POST | Payment success callback |
/order/cancelOrder |
POST | Cancel a single order |
/order/cancelTimeOutOrder |
POST | Cancel all timed-out orders |
Warning
Orders that are not paid within the configured timeout are automatically cancelled via RabbitMQ dead-letter queue. The timeout is set in the order settings (managed via admin API).
4.7 Member Features (Portal)
| Endpoint | Method | Description |
|---|---|---|
/sso/register |
POST | Member registration |
/sso/login |
POST | Member login |
/member/address/list |
GET | Shipping addresses |
/member/address/add |
POST | Add address |
/member/address/update/{id} |
POST | Update address |
/member/address/delete/{id} |
POST | Delete address |
/member/coupon/list |
GET | Member's coupons |
/member/coupon/add/{couponId} |
POST | Claim a coupon |
/member/coupon/list/cart/{type} |
GET | Coupons applicable to cart |
/member/attention/add |
POST | Follow a brand |
/member/attention/list |
GET | Brand follows |
/member/productCollection/add |
POST | Collect a product |
/member/productCollection/list |
GET | Product collections |
/member/readHistory/list |
GET | Browse history |
4.8 Homepage Content (Portal)
| Endpoint | Method | Description |
|---|---|---|
/home/content |
GET | Homepage aggregated content |
/home/recommendProductList |
GET | Recommended products |
/home/productCateList/{parentId} |
GET | Product categories |
/home/subjectList |
GET | Subject/topic list |
/home/hotProductList |
GET | Hot products |
/home/newProductList |
GET | New products |
4.9 Payment (Portal)
| Endpoint | Method | Description |
|---|---|---|
/alipay/pay |
GET | Desktop Alipay payment page |
/alipay/webPay |
GET | Mobile Alipay payment page |
/alipay/notify |
POST | Alipay async notification callback |
/alipay/query |
GET | Query payment status |
4.10 Product Search
| Endpoint | Method | Description |
|---|---|---|
/esProduct/importAll |
POST | Import all products to ES |
/esProduct/search |
GET | Search products (keyword, filters) |
/esProduct/create/{id} |
POST | Index a single product |
/esProduct/delete/{id} |
GET | Remove product from index |
/esProduct/delete/batch |
POST | Batch remove from index |
Tip
After initial setup, run
POST /esProduct/importAllto populate the Elasticsearch index with product data from MySQL.
5. Common Tasks
Register an Admin and Assign Permissions
- Log in as the default admin (
admin/123456) POST /admin/registerwith name, username, password, emailGET /role/listto find the target role IDPOST /admin/role/update?adminId={id}&roleIds={roleId}to assign roles
Create a Product with SKU Variants
- Ensure product categories exist (
GET /productCategory/list/withChildren) - Ensure a brand exists (
GET /brand/listAll) POST /product/createwith full product JSON includingskuStockListarray (each entry hasprice,stock,sp1/sp2/sp3for specification values,skuCode)
Process a Customer Order
- Customer adds items to cart (
POST /cart/add) - Customer confirms order (
POST /order/confirmOrder) — returns available addresses, coupons, cart totals - Customer places order (
POST /order/generateOrder) withmemberReceiveAddressId,couponId,payType - Customer pays (Alipay redirects back; async
/alipay/notifyupdates order status) - Admin ships order (
POST /order/update/delivery) with tracking info
Set Up a Flash Sale Promotion
POST /flash/create— create flash promotion event (name, start/end dates)GET /flashSession/list— list time sessionsPOST /flashProductRelation/create— bind products to session with flash prices
Import Products to Elasticsearch
curl -X POST http://localhost:8081/esProduct/importAll \
-H "Authorization: Bearer <token>"
{"code": 200, "message": "操作成功", "data": 48}
This syncs all products from MySQL to Elasticsearch for full-text search.
Handle a Return Application
- Customer submits return request via portal API
- Admin lists returns:
GET /returnApply/list - Admin reviews and updates status:
POST /returnApply/update/statuswith approval/rejection details
6. Troubleshooting
Error: Swagger UI returns 404
Cause: Spring Boot 2.6+ defaults to PathPatternParser which conflicts with Springfox 3.0.
Solution:
Ensure this is set in application.yml:
spring:
mvc:
pathmatch:
matching-strategy: ant_path_matcher
Prevention: This is already configured in the project. If upgrading Spring Boot, verify this setting remains.
Error: 401 Unauthorized on all endpoints
Cause: JWT token missing, expired, or malformed.
Solution:
- Obtain a fresh token via
/admin/loginor/sso/login - Include it in requests:
Authorization: Bearer <token> - If the token expired, use
/admin/token/refresh(within token lifetime)
Prevention: Implement token refresh logic in your client before expiration.
Error: Cannot connect to MySQL on startup
Cause: MySQL container not running or connection credentials wrong.
Solution:
- Verify MySQL is running:
docker ps | grep mysql - Check
application-dev.ymldatasource URL, username, and password match your setup - Ensure the
malldatabase exists:mysql -u root -proot -e "SHOW DATABASES;"
Error: Orders not being auto-cancelled
Cause: RabbitMQ not running or queue configuration issue.
Solution:
- Confirm RabbitMQ is running:
docker ps | grep rabbitmq - Check the management UI at
http://localhost:15672(guest/guest) — verifymall.order.cancelandmall.order.cancel.ttlqueues exist - Verify the portal module started successfully (it registers the queues on boot)
Prevention: Always start RabbitMQ before mall-portal.
Note
The order timeout cancellation works via a dead-letter queue. Orders are sent to a TTL queue; when the message expires, RabbitMQ routes it to the cancel queue where
CancelOrderReceiverprocesses the cancellation. (Community issue #499)
Error: Elasticsearch search returns empty results
Cause: Product index not populated.
Solution:
curl -X POST http://localhost:8081/esProduct/importAll
Prevention: Run the import after database changes or on first setup.
Error: MinIO upload fails with access denied
Cause: MinIO credentials or bucket policy not configured.
Solution:
- Access MinIO console at
http://localhost:9001(minioadmin/minioadmin) - Create the required bucket
- Verify
minio.*config inapplication-dev.ymlmatches your MinIO setup
Error: NumberFormatException on Swagger page load
Cause: Known Springfox 3.0 issue with certain model annotations.
Solution: The project includes swagger-models:1.6.0 and swagger-annotations:1.6.0 which fix this. If you see the error after dependency updates, re-pin these versions.
Warning
If running with JDK 11+, the
javax.xml.bind:jaxb-apidependency is required (already included in the parent POM). Removing it causesClassNotFoundExceptionon JWT operations.
Error: Flash sale time returns incorrect values
Cause: Timezone mismatch between application and database. (Community issue #532)
Solution: Ensure both application (TZ=Asia/Shanghai) and MySQL (character-set-server=utf8mb4) are configured consistently. The Docker Compose files set this via environment variables.
Error: Coupon discount calculation appears wrong for edge cases
Cause: Floating-point precision issues in promotion amount apportionment across order items. (Community issue #356)
Solution: This is a known limitation of the current algorithm — fractional cent differences may occur when splitting coupon amounts across multiple items.
7. FAQ
Q: Is mall a monolithic application or microservices?
This repository is the monolithic version. Each module (mall-admin, mall-portal, mall-search) runs as a separate Spring Boot JAR but shares the same database. The author maintains a separate mall-swarm repository for the microservices (Spring Cloud) version.
Q: What is the default admin account?
Username admin, password 123456. This is seeded in the mall.sql database schema.
Q: Can I use this without Docker?
Yes. Install MySQL, Redis, MongoDB, RabbitMQ, and Elasticsearch natively, then configure connection details in the application-dev.yml files for each module.
Q: How do I add new API endpoints?
Create a controller in the appropriate module's controller package with @Controller, @Api, and @RequestMapping annotations. The endpoint will automatically appear in Swagger UI.
Q: Is there English language support?
The codebase and default data are in Chinese. Community issue #35 requests English translation but it has not been implemented. API responses use Chinese messages by default (e.g., "操作成功" for success).
Q: How do I customize the JWT secret and expiration?
Set jwt.secret and jwt.expiration (in seconds) in the module's application.yml. See the Admin Guide for security recommendations.
Caution
The default JWT secret in the codebase is a weak placeholder. In production, always override
jwt.secretwith a strong, unique value. (See security issue #948)
Q: How does the dynamic authorization system work?
Admin module registers all URL resources in the ums_resource table. Roles are assigned specific resources. At runtime, DynamicSecurityFilter intercepts requests and checks whether the current user's role(s) grant access to the requested URL pattern.
Q: Can I run just the admin module without portal/search?
Yes. mall-admin only requires MySQL and Redis. MongoDB, RabbitMQ, and Elasticsearch are only needed by mall-portal and mall-search.
Q: What is the mall-demo module for?
It's a demonstration/learning module showing Spring Security integration patterns (different from the main mall-security module approach). It's not needed for production.
Q: How do I integrate with a different payment gateway?
The Alipay integration lives entirely in mall-portal's AlipayController and AlipayService. Implement a new service following the same pattern and add a controller with your gateway's SDK.