1. Architecture Overview
Mall is a multi-module Spring Boot 2.7.5 e-commerce backend platform structured as a monolithic application with clear module boundaries. It provides REST APIs for both back-office administration and customer-facing shopping operations, backed by MySQL, Redis, MongoDB, Elasticsearch, and RabbitMQ.
The system follows a layered architecture within each module: Controller → Service → DAO/Mapper, with a shared security module providing JWT-based authentication and dynamic URL-level authorization across all deployable modules.
┌─────────────────────────────────────────────────────────────────┐
│ Client Applications │
│ (Admin SPA, Mobile App, Web Storefront) │
└──────────┬──────────────────┬──────────────────┬────────────────┘
│ │ │
┌─────▼─────┐ ┌──────▼──────┐ ┌─────▼─────┐
│ mall-admin │ │ mall-portal │ │mall-search│
│ :8080 │ │ :8085 │ │ :8081 │
└─────┬─────┘ └──────┬──────┘ └─────┬─────┘
│ │ │
┌─────▼──────────────────▼──────────────────▼─────┐
│ mall-security (JWT + RBAC) │
└─────────────────────┬───────────────────────────┘
│
┌─────────────────────▼───────────────────────────┐
│ mall-mbg │
│ (MyBatis Generated Mappers/Models) │
└─────────────────────┬───────────────────────────┘
│
┌─────────────────────▼───────────────────────────┐
│ mall-common │
│ (Redis, Swagger, Pagination, Error Handling) │
└──┬──────────┬──────────┬──────────┬─────────────┘
│ │ │ │
┌────▼───┐ ┌───▼───┐ ┌───▼────┐ ┌───▼─────┐
│ MySQL │ │ Redis │ │MongoDB │ │RabbitMQ │
│ 5.7 │ │ 7 │ │ 4 │ │ 3.9 │
└────────┘ └───────┘ └────────┘ └─────────┘
│
┌────────────▼────────────┐
│ Elasticsearch 7.17 │
└─────────────────────────┘
Component Inventory
| Component | Module | Port | Role |
|---|---|---|---|
| Admin API | mall-admin |
8080 | Back-office management (products, orders, promotions, users) |
| Portal API | mall-portal |
8085 | Customer-facing (cart, orders, member, payments) |
| Search API | mall-search |
8081 | Elasticsearch-backed product search |
| Security | mall-security |
— | Shared JWT auth + dynamic authorization library |
| MBG | mall-mbg |
— | MyBatis Generator output (mappers, models, examples) |
| Common | mall-common |
— | Shared utilities (Redis, Swagger, pagination, exceptions) |
| Demo | mall-demo |
8082 | Learning/demo module (not production) |
Technology Stack
| Layer | Technology | Version |
|---|---|---|
| Framework | Spring Boot | 2.7.5 |
| Security | Spring Security + JWT (jjwt) | 5.7.x / 0.9.1 |
| ORM | MyBatis + PageHelper | 3.5.10 / 5.3.2 |
| Database | MySQL | 5.7+ (via mysql-connector 8.0.29) |
| Connection Pool | Druid | 1.2.14 |
| Cache | Redis (Spring Data Redis) | 7 |
| Document Store | MongoDB (Spring Data MongoDB) | 4 |
| Search | Elasticsearch (Spring Data ES) | 7.17.x |
| Message Queue | RabbitMQ (Spring AMQP) | 3.9 |
| Object Storage | MinIO / Aliyun OSS | 8.4.5 / 2.5.0 |
| Payment | Alipay SDK | 4.38.61 |
| API Docs | Springfox (Swagger 2) | 3.0.0 |
| Utilities | Hutool | 5.8.9 |
| Code Gen | Lombok | Latest |
| Logging | Logstash Logback Encoder | 7.2 |
| Build | Maven + fabric8 Docker plugin | — / 0.40.2 |
| Java | JDK | 8 (source/target) |
Note
The project targets Java 8 but includes
javax.xml.bind:jaxb-api:2.3.1for JDK 11+ compatibility. The codebase uses Spring Security's pre-6.0 API style (imperativeHttpSecuritychain, not the newer Lambda DSL).
Data Flow: Order Placement
- Customer calls
POST /order/generateOrderwith address, coupon, payment type OmsPortalOrderServiceImplvalidates cart, calculates promotions, deducts stock- Order record inserted into MySQL with status
0(pending payment) CancelOrderSendersends order ID to RabbitMQ TTL queue (mall.order.cancel.ttl)- If paid:
POST /order/paySuccessupdates status to1 - If TTL expires: message routed to dead-letter queue →
CancelOrderReceivercancels order, restores stock
2. System Requirements
Hardware (Minimum for Development)
| Resource | Minimum | Recommended |
|---|---|---|
| RAM | 8 GB | 16 GB |
| CPU | 4 cores | 8 cores |
| Disk | 20 GB | 50 GB (Elasticsearch data) |
Software Dependencies
| Software | Required Version | Notes |
|---|---|---|
| JDK | 8+ (8 preferred) | Source level 1.8 |
| Maven | 3.6+ | For building |
| Docker + Compose | Latest | For infrastructure |
| MySQL | 5.7+ | utf8mb4 charset |
| Redis | 7+ | AOF persistence recommended |
| MongoDB | 4+ | For member data (collections, history) |
| RabbitMQ | 3.9+ | Management plugin required |
| Elasticsearch | 7.17.x | Single-node mode for dev |
| Kibana | 7.17.x | Optional log visualization |
| Logstash | 7.17.x | Optional log aggregation |
| MinIO | Latest | Object storage |
| Nginx | 1.22+ | Frontend proxy |
3. Configuration Reference
Configuration Files
| File | Module | Format | Purpose |
|---|---|---|---|
application.yml |
Each module | YAML | Shared Spring config |
application-dev.yml |
Each module | YAML | Development overrides |
application-prod.yml |
Each module | YAML | Production overrides |
generatorConfig.xml |
mall-mbg | XML | MyBatis Generator config |
generator.properties |
mall-mbg | Properties | DB connection for codegen |
logback-spring.xml |
mall-common | XML | Logging configuration |
Spring Configuration Keys
Database (all modules)
| Key | Type | Example | Description |
|---|---|---|---|
spring.datasource.url |
String | jdbc:mysql://localhost:3306/mall?... |
JDBC connection URL |
spring.datasource.username |
String | root |
DB username |
spring.datasource.password |
String | root |
DB password |
spring.datasource.druid.* |
— | — | Druid pool settings (initial/min/max size, etc.) |
Redis
| Key | Type | Default | Description |
|---|---|---|---|
spring.redis.host |
String | localhost |
Redis host |
spring.redis.port |
Integer | 6379 |
Redis port |
spring.redis.database |
Integer | 0 |
Redis DB index |
spring.redis.password |
String | — | Redis password (if set) |
spring.redis.timeout |
Duration | 3000ms |
Connection timeout |
MongoDB (mall-portal)
| Key | Type | Example | Description |
|---|---|---|---|
spring.data.mongodb.host |
String | localhost |
MongoDB host |
spring.data.mongodb.port |
Integer | 27017 |
MongoDB port |
spring.data.mongodb.database |
String | mall-port |
Database name |
RabbitMQ (mall-portal)
| Key | Type | Example | Description |
|---|---|---|---|
spring.rabbitmq.host |
String | localhost |
Broker host |
spring.rabbitmq.port |
Integer | 5672 |
AMQP port |
spring.rabbitmq.virtual-host |
String | / |
Virtual host |
spring.rabbitmq.username |
String | guest |
Username |
spring.rabbitmq.password |
String | guest |
Password |
Elasticsearch (mall-search)
| Key | Type | Example | Description |
|---|---|---|---|
spring.elasticsearch.uris |
String | http://localhost:9200 |
ES cluster URL |
JWT Security
| Key | Type | Example | Description |
|---|---|---|---|
jwt.tokenHeader |
String | Authorization |
Header name |
jwt.secret |
String | — | HMAC signing key (HS512) |
jwt.expiration |
Integer | 604800 |
Token TTL in seconds |
jwt.tokenHead |
String | Bearer |
Token prefix |
Important
The
jwt.secretvalue MUST be changed from any default in production. Issue #948 demonstrates that a weak default enables authentication bypass. Use a cryptographically random string of at least 64 characters.
Security Whitelist
| Key | Type | Description |
|---|---|---|
secure.ignored.urls |
List | URL patterns that bypass JWT auth |
Typical whitelist entries:
secure:
ignored:
urls:
- /swagger-ui/**
- /swagger-resources/**
- /v2/api-docs
- /**/admin/login
- /**/sso/login
- /**/sso/register
- /actuator/**
Aliyun OSS (mall-admin)
| Key | Type | Description |
|---|---|---|
aliyun.oss.endpoint |
String | OSS endpoint URL |
aliyun.oss.accessKeyId |
String | Access key |
aliyun.oss.accessKeySecret |
String | Secret key |
aliyun.oss.bucketName |
String | Bucket name |
aliyun.oss.policy.expire |
Integer | Policy expiration (seconds) |
aliyun.oss.maxSize |
Integer | Max upload size (MB) |
aliyun.oss.callback |
String | Callback URL |
aliyun.oss.dir.prefix |
String | Upload path prefix |
MinIO (mall-admin)
| Key | Type | Description |
|---|---|---|
minio.endpoint |
String | MinIO API endpoint |
minio.bucketName |
String | Bucket name |
minio.accessKey |
String | Access key |
minio.secretKey |
String | Secret key |
Alipay (mall-portal)
| Key | Type | Description |
|---|---|---|
alipay.gatewayUrl |
String | Alipay gateway URL |
alipay.appId |
String | Application ID |
alipay.appPrivateKey |
String | App RSA private key |
alipay.alipayPublicKey |
String | Alipay RSA public key |
alipay.returnUrl |
String | Sync return URL |
alipay.notifyUrl |
String | Async notification URL |
Caution
Never commit Alipay private keys or OSS secrets to source control. Use environment variables or external secret management in production.
Spring MVC / Swagger Compatibility
| Key | Value | Required By |
|---|---|---|
spring.mvc.pathmatch.matching-strategy |
ant_path_matcher |
Springfox 3.0 |
4. Deployment & Scaling
Docker Image Build
The project uses the fabric8 Docker Maven plugin configured in the parent POM:
# Build all modules + Docker images
mvn clean package -DskipTests
Image naming convention: mall/{module-name}:1.0-SNAPSHOT
The Docker build base image is openjdk:8 with entrypoint:
java -jar -Dspring.profiles.active=prod /${module}.jar
Remote Docker host is configured at ${docker.host} (default: http://192.168.3.101:2375).
Infrastructure Deployment
Environment services (document/docker/docker-compose-env.yml):
docker compose -f document/docker/docker-compose-env.yml up -d
This deploys: MySQL, Redis, Nginx, RabbitMQ, Elasticsearch, Logstash, Kibana, MongoDB, MinIO.
Application services (document/docker/docker-compose-app.yml):
docker compose -f document/docker/docker-compose-app.yml up -d
This deploys: mall-admin (:8080), mall-search (:8081), mall-portal (:8085).
Port Mapping
| Service | Host Port | Container Port |
|---|---|---|
| mall-admin | 8080 | 8080 |
| mall-search | 8081 | 8081 |
| mall-portal | 8085 | 8085 |
| MySQL | 3306 | 3306 |
| Redis | 6379 | 6379 |
| Nginx | 80 | 80 |
| RabbitMQ AMQP | 5672 | 5672 |
| RabbitMQ Management | 15672 | 15672 |
| Elasticsearch HTTP | 9200 | 9200 |
| Elasticsearch Transport | 9300 | 9300 |
| Logstash | 4560-4563 | 4560-4563 |
| Kibana | 5601 | 5601 |
| MongoDB | 27017 | 27017 |
| MinIO API | 9090 | 9000 |
| MinIO Console | 9001 | 9001 |
Volume Mounts
| Service | Host Path | Container Path | Purpose |
|---|---|---|---|
| MySQL | /mydata/mysql/data |
/var/lib/mysql |
Data persistence |
| MySQL | /mydata/mysql/conf |
/etc/mysql |
Custom config |
| MySQL | /mydata/mysql/log |
/var/log/mysql |
Logs |
| Redis | /mydata/redis/data |
/data |
AOF persistence |
| Elasticsearch | /mydata/elasticsearch/plugins |
.../plugins |
Plugins (e.g., IK analyzer) |
| Elasticsearch | /mydata/elasticsearch/data |
.../data |
Index data |
| MongoDB | /mydata/mongo/db |
/data/db |
Data persistence |
| MinIO | /mydata/minio/data |
/data |
Object storage |
| Nginx | /mydata/nginx/conf |
/etc/nginx |
Nginx config |
| Nginx | /mydata/nginx/html |
.../html |
Static files |
| Apps | /mydata/app/{name}/logs |
/var/logs |
Application logs |
Tip
All persistent data resides under
/mydata/. Back up this directory for full system recovery.
Scaling Considerations
- mall-admin: Stateless — scale horizontally behind a load balancer. Redis handles session/cache.
- mall-portal: Stateless — scale horizontally. Ensure shared Redis for member caching.
- mall-search: Stateless — scale horizontally. All state lives in Elasticsearch.
- MySQL: Vertical scaling or read replicas. The application uses a single datasource.
- Elasticsearch: Add nodes to the cluster and change
discovery.typefromsingle-node.
Note
The Docker Compose files use
external_linksfor inter-container communication (a deprecated feature). For production, use Docker networks or Kubernetes service discovery.
5. Operations
Health Checks
Each module exposes Spring Boot Actuator at /actuator/health:
curl http://localhost:8080/actuator/health
curl http://localhost:8085/actuator/health
curl http://localhost:8081/actuator/health
Log Management
Logging is configured via mall-common/src/main/resources/logback-spring.xml with Logstash integration:
- Application logs write to
/var/logs/(mapped to/mydata/app/{module}/logs/on host) - Logstash collects from ports 4560-4563 (one per module)
- Kibana provides visualization at port 5601
Database Initialization
mysql -u root -proot < document/sql/mall.sql
The SQL file creates:
- Database
mall - All ~70 tables with schema (prefixed:
cms_*,oms_*,pms_*,sms_*,ums_*) - Seed data (admin user, default categories, demo products)
MyBatis Generator (Code Regeneration)
To regenerate mapper/model classes after schema changes:
- Update
mall-mbg/src/main/resources/generator.propertieswith DB connection - Update
mall-mbg/src/main/resources/generatorConfig.xmlwith target tables - Run
Generator.javamain class inmall-mbg
Warning
Regeneration overwrites all files in
mall-mbg/src/main/java/com/macro/mall/mapper/andmall-mbg/src/main/java/com/macro/mall/model/. Custom DAO classes inmall-adminormall-portaldao/packages are safe — they're in separate packages.
Elasticsearch Index Management
Import all products:
curl -X POST http://localhost:8081/esProduct/importAll
The EsProduct document maps product data with nested EsProductAttributeValue objects. The search service supports keyword matching, brand/category filtering, and attribute aggregation.
RabbitMQ Queue Setup
Queues are declared automatically by mall-portal on startup via RabbitMqConfig:
| Queue | Exchange | Routing Key | Purpose |
|---|---|---|---|
mall.order.cancel |
mall.order.direct |
mall.order.cancel |
Actual cancellation processing |
mall.order.cancel.ttl |
mall.order.direct.ttl |
mall.order.cancel.ttl |
Delay queue (dead-letter) |
The TTL queue forwards expired messages to the cancel queue using dead-letter exchange configuration.
Tip
Monitor queue depth via RabbitMQ Management UI (
http://localhost:15672). A growingmall.order.cancel.ttlqueue during peak hours is normal; a growingmall.order.cancelqueue indicates the consumer is falling behind.
Scheduled Tasks
mall-portal enables Spring's @EnableScheduling. The OrderTimeOutCancelTask runs on a cron schedule to catch any orders that weren't cancelled via the RabbitMQ mechanism (belt-and-suspenders approach).
6. Performance
Redis Caching Strategy
- Cache TTL: 1 day (configured in
BaseRedisConfig) - Serialization: Jackson2 with type information (enables proper deserialization)
- Cache service:
RedisServiceImplprovides get/set/delete/expire operations used byUmsAdminCacheServiceandUmsMemberCacheService - Cache failure resilience:
RedisCacheAspectwraps all*CacheServicemethods — if Redis is down, cache operations silently fail unless annotated with@CacheException
Note
The
@CacheExceptionannotation marks cache methods that MUST throw on failure (e.g., login verification code validation). All other cache methods degrade gracefully when Redis is unavailable.
Connection Pooling
Druid connection pool is configured per module in application.yml. Key tuning parameters:
initialSize— initial connections on startupminIdle— minimum idle connectionsmaxActive— maximum concurrent connectionsmaxWait— max wait time for a connection from pool
Pagination
All list operations use PageHelper (MyBatis plugin) or Spring Data pagination:
CommonPage.restPage(List)— wraps MyBatis PageHelper resultsCommonPage.restPage(Page)— wraps Spring Data Page results (MongoDB, ES)
7. Security
Authentication Architecture
Request → JwtAuthenticationTokenFilter → SecurityFilterChain
├── Token present & valid → SecurityContext populated → proceed
├── Token missing/invalid → RestAuthenticationEntryPoint (401)
└── Token valid but insufficient permissions → RestfulAccessDeniedHandler (403)
JWT Implementation (JwtTokenUtil):
- Algorithm: HS512
- Claims:
sub(username),created(issue timestamp as millis) - Expiration: configurable via
jwt.expiration(seconds) - Token refresh: only re-issues if current token is >30 min old (
tokenRefreshJustBefore)
Dynamic URL-Based Authorization
When DynamicSecurityService bean is present (e.g., in mall-admin), the system enforces URL-level authorization:
DynamicSecurityMetadataSourceloads allums_resourceentries on startup- For each request, it matches the URL against resource patterns
DynamicAccessDecisionManagerchecks if the user's roles include the required resource- This filter runs AFTER
JwtAuthenticationTokenFilterand BEFOREFilterSecurityInterceptor
Warning
The
mall-portalmodule does NOT enable dynamic resource authorization (noDynamicSecurityServicebean). It relies solely on JWT authentication — any authenticated member can access all portal endpoints. If you need endpoint-level restrictions for members, you must implement it.
Password Security
- Algorithm: BCrypt (
BCryptPasswordEncoder) - Storage:
ums_admin.passwordcolumn stores BCrypt hash - No password complexity enforcement in code (business logic only)
Security Whitelist
URLs in secure.ignored.urls completely bypass the security filter chain. Default whitelist includes:
- Swagger endpoints
- Login/register endpoints
- Actuator health check
- Static resources
Known Security Issues
| Issue | Severity | Status | Detail |
|---|---|---|---|
| #948 | High | Closed (documented) | Default jwt.secret is weak — enables token forgery if not changed |
| CORS | Medium | By design | GlobalCorsConfig allows all origins (*) — restrict in production |
| CSRF | Low | Disabled | CSRF disabled (stateless JWT — expected for API-only services) |
Caution
The CORS configuration (
addAllowedOriginPattern("*")) is suitable for development only. In production, restrict to your actual frontend domain(s).
Session Management
Sessions are disabled (SessionCreationPolicy.STATELESS). All state is carried in the JWT token. Redis is used for:
- Admin/member data caching (not session storage)
- Temporary verification codes (if implemented)
8. Developer Internals
Repository Structure
mall/
├── pom.xml # Parent POM (dependency management)
├── mall-common/ # Shared library
│ └── src/main/java/.../common/
│ ├── api/ # CommonResult, CommonPage, ResultCode
│ ├── config/ # BaseRedisConfig, BaseSwaggerConfig
│ ├── domain/ # SwaggerProperties, WebLog
│ ├── exception/ # ApiException, GlobalExceptionHandler
│ ├── log/ # WebLogAspect (request logging)
│ ├── service/ # RedisService interface + impl
│ └── util/ # RequestUtil
├── mall-mbg/ # MyBatis Generator
│ └── src/main/java/.../
│ ├── mapper/ # 76 mapper interfaces
│ ├── model/ # 76 model + 76 example classes
│ ├── Generator.java # Code generation entry
│ └── CommentGenerator.java # Custom comment generator
├── mall-security/ # Security library
│ └── src/main/java/.../security/
│ ├── annotation/ # @CacheException
│ ├── aspect/ # RedisCacheAspect
│ ├── component/ # Filters, handlers, dynamic auth
│ ├── config/ # SecurityConfig, IgnoreUrlsConfig
│ └── util/ # JwtTokenUtil, SpringUtil
├── mall-admin/ # Admin API (deployable)
│ └── src/main/java/.../
│ ├── config/ # CORS, Security, MyBatis, OSS, Swagger
│ ├── controller/ # 30+ REST controllers
│ ├── dao/ # Custom DAO interfaces
│ ├── dto/ # Request/response DTOs
│ ├── bo/ # Business objects
│ ├── service/ # Service interfaces
│ ├── service/impl/ # Service implementations
│ └── validator/ # Custom validation (@FlagValidator)
├── mall-portal/ # Portal API (deployable)
│ └── src/main/java/.../portal/
│ ├── config/ # Alipay, RabbitMQ, Jackson, CORS, etc.
│ ├── controller/ # 14 REST controllers
│ ├── component/ # CancelOrderSender/Receiver, scheduled task
│ ├── dao/ # Custom DAO interfaces
│ ├── domain/ # Domain models (Mongo docs, DTOs)
│ ├── repository/ # MongoDB repositories
│ ├── service/ # Service interfaces
│ ├── service/impl/ # Service implementations
│ └── util/ # DateUtil
├── mall-search/ # Search API (deployable)
│ └── src/main/java/.../search/
│ ├── config/ # MyBatis, Swagger
│ ├── controller/ # EsProductController
│ ├── dao/ # EsProductDao (MyBatis)
│ ├── domain/ # EsProduct, EsProductAttributeValue
│ ├── repository/ # EsProductRepository (Spring Data ES)
│ ├── service/ # EsProductService
│ └── service/impl/ # EsProductServiceImpl
├── mall-demo/ # Demo module (not production)
└── document/ # Deployment & reference docs
├── docker/ # Docker Compose files, nginx.conf
├── sh/ # Deployment shell scripts
├── sql/ # Database schema (mall.sql)
├── postman/ # API collections
├── elk/ # Logstash config
├── reference/ # Developer reference docs
└── resource/ # Architecture diagrams, screenshots
Module Dependency Graph
mall-common ← mall-mbg ← mall-security ← mall-admin
↑ ← mall-portal
↑ ← mall-search
└── mall-demo
mall-common: no internal dependencies (only Spring starters)mall-mbg: depends onmall-common(uses Redis, Swagger base, pagination)mall-security: depends onmall-common(uses Redis for caching)mall-admin: depends onmall-mbg+mall-security+ Aliyun OSS + MinIOmall-portal: depends onmall-mbg+mall-security+ MongoDB + RabbitMQ + Alipaymall-search: depends onmall-mbg+ Elasticsearch (excludes Redis from mall-mbg transitively)
Database Schema Overview
The schema uses prefixed table naming to organize by domain:
| Prefix | Domain | Key Tables |
|---|---|---|
cms_ |
Content Management | cms_subject, cms_prefrence_area, cms_help |
oms_ |
Order Management | oms_order, oms_order_item, oms_cart_item, oms_order_return_apply |
pms_ |
Product Management | pms_product, pms_brand, pms_product_category, pms_sku_stock, pms_product_attribute |
sms_ |
Sales/Marketing | sms_coupon, sms_flash_promotion, sms_home_advertise, sms_home_brand |
ums_ |
User Management | ums_admin, ums_role, ums_resource, ums_member, ums_menu |
Total: ~70 tables with full referential integrity.
API Response Patterns
Standard success response:
{"code": 200, "message": "操作成功", "data": {...}}
Standard error responses:
{"code": 401, "message": "暂未登录或token已经过期", "data": null}
{"code": 403, "message": "没有相关权限", "data": null}
{"code": 404, "message": "参数检验失败", "data": null}
{"code": 500, "message": "操作失败", "data": null}
Paginated response:
{
"code": 200,
"data": {
"pageNum": 1,
"pageSize": 5,
"totalPage": 10,
"total": 48,
"list": [...]
}
}
Code Patterns and Conventions
Controller pattern:
- Annotated with
@Controller(not@RestController) +@ResponseBodyper method @Apiand@Tagfor Swagger documentation@RequestMappingon class for base path- Return
CommonResult<T>orCommonResult<CommonPage<T>>
Service pattern:
- Interface in
service/package - Implementation in
service/impl/with@Service - Business logic lives here; controllers are thin dispatchers
DAO pattern (custom queries):
- Interface in
dao/package (annotated with MyBatis@Mappervia@MapperScan) - XML mapping in
resources/dao/directory - Used for complex queries beyond single-table CRUD (which uses MBG mappers)
Validation:
- Custom
@FlagValidatorannotation validates integer fields against allowed values - Standard JSR-303 validation via Spring Boot Validation starter
Exception handling:
GlobalExceptionHandlercatchesApiExceptionand validation errorsAsserts.fail(message)throwsApiExceptionwith custom message- Framework-level:
RestAuthenticationEntryPoint(401),RestfulAccessDeniedHandler(403)
Testing
The project has minimal test coverage:
mall-admin:PmsDaoTests(product DAO integration test)mall-portal:PortalProductDaoTests(product DAO test)mall-search:MallSearchApplicationTests(context load test)mall-demo:MallDemoApplicationTests(context load test)
Tests are skipped by default (<skipTests>true</skipTests> in parent POM).
9. Integration Points
Swagger UI (API Documentation)
Each deployable module auto-generates Swagger documentation:
| Module | Swagger UI | API Docs JSON |
|---|---|---|
| mall-admin | http://localhost:8080/swagger-ui/ |
/v2/api-docs |
| mall-portal | http://localhost:8085/swagger-ui/ |
/v2/api-docs |
| mall-search | http://localhost:8081/swagger-ui/ |
/v2/api-docs |
Security-enabled Swagger configs (admin, portal) include the Authorization header parameter for testing protected endpoints.
Alipay Payment Integration
mall-portal integrates Alipay via the official Java SDK:
| Endpoint | Flow |
|---|---|
/alipay/pay |
Generates desktop payment page (redirect) |
/alipay/webPay |
Generates mobile payment page (redirect) |
/alipay/notify |
Receives async payment confirmation from Alipay |
/alipay/query |
Queries transaction status by trade number |
Configuration binds to prefix alipay.* via AlipayConfig (@ConfigurationProperties).
External Storage
MinIO (preferred for self-hosted):
MinioControllerhandles file upload/delete- Bucket policy set to allow public read of uploaded files
- Configured via
minio.*properties
Aliyun OSS (cloud option):
OssControllergenerates pre-signed upload policies- Supports browser-direct upload with server callback
- Configured via
aliyun.oss.*properties
Logstash Integration
logback-spring.xml in mall-common configures appenders that send structured JSON logs to Logstash:
- Port 4560: Default application logs
- Ports 4561-4563: Available for per-module separation
The WebLogAspect AOP aspect logs all controller method invocations with request/response details into structured WebLog objects.
MongoDB Collections
mall-portal uses MongoDB for:
MemberReadHistory— product browsing historyMemberProductCollection— product collections/favoritesMemberBrandAttention— brand follows
These use Spring Data MongoDB repositories with automatic pagination support.
10. Troubleshooting
Startup Failures
Error: Failed to configure a DataSource
Cause: MySQL not reachable or credentials incorrect.
Solution:
- Verify MySQL is running:
docker ps | grep mysql - Test connection:
mysql -h localhost -u root -proot - Verify
application-dev.ymldatasource configuration
Error: Connection refused to Redis/MongoDB/RabbitMQ
Cause: Infrastructure service not started.
Solution:
docker compose -f document/docker/docker-compose-env.yml up -d
docker ps # verify all containers are running
Error: BeanCreationException related to Elasticsearch
Cause: Elasticsearch version mismatch or not running.
Solution: Ensure ES 7.17.x is running. Spring Data ES in Boot 2.7.5 targets ES 7.17. Using ES 8.x will fail.
Runtime Issues
Dynamic security metadata not loading
Cause: ums_resource table empty or DynamicSecurityService bean not registered.
Solution:
- Check
SELECT * FROM ums_resource— should have entries - Verify
MallSecurityConfiginmall-admindeclaresdynamicSecurityService()bean
Note
Community issue #884 reports path matching optimization needed for the dynamic security filter — URL patterns with path variables may not match correctly in all edge cases.
Single-product order generation fails
Cause: Known issue with generating orders for individual products (vs. cart-based). (Community issue #469)
Solution: Use the cart-based flow: add product to cart, then generate order from cart contents.
Promotion calculation errors with full-reduction
Cause: Edge case in coupon amount distribution algorithm. (Community issue #492)
Solution: Verify promotion rules don't create conflicting overlapping conditions.
Warning
The coupon apportionment algorithm distributes discount amounts proportionally across order items. Rounding errors of ±1 cent can occur with certain item price/quantity combinations. (Issue #356)
11. Quick Reference
API Endpoint Summary
mall-admin (port 8080)
| Controller | Base Path | Operations |
|---|---|---|
UmsAdminController |
/admin |
Login, register, list, update, delete, role assignment |
UmsRoleController |
/role |
CRUD roles, allocate resources/menus |
UmsResourceController |
/resource |
CRUD API resources |
UmsMenuController |
/menu |
CRUD navigation menus |
PmsProductController |
/product |
CRUD products, batch operations |
PmsBrandController |
/brand |
CRUD brands |
PmsProductCategoryController |
/productCategory |
CRUD categories |
PmsProductAttributeController |
/productAttribute |
CRUD attributes |
PmsProductAttributeCategoryController |
/productAttribute/category |
Attribute categories |
PmsSkuStockController |
/sku |
SKU stock management |
OmsOrderController |
/order |
Order list, detail, delivery, close |
OmsOrderReturnApplyController |
/returnApply |
Return processing |
OmsOrderReturnReasonController |
/returnReason |
Return reason management |
OmsOrderSettingController |
/orderSetting |
Order timeout settings |
SmsCouponController |
/coupon |
Coupon CRUD |
SmsFlashPromotionController |
/flash |
Flash sale events |
SmsFlashPromotionSessionController |
/flashSession |
Flash sale time slots |
SmsFlashPromotionProductRelationController |
/flashProductRelation |
Flash sale products |
SmsHomeAdvertiseController |
/home/advertise |
Homepage ads |
SmsHomeBrandController |
/home/brand |
Homepage brands |
SmsHomeNewProductController |
/home/newProduct |
Homepage new arrivals |
SmsHomeRecommendProductController |
/home/recommendProduct |
Homepage recommendations |
SmsHomeRecommendSubjectController |
/home/recommendSubject |
Homepage subjects |
CmsPrefrenceAreaController |
/prefrenceArea |
Preference areas |
CmsSubjectController |
/subject |
Content subjects |
OmsCompanyAddressController |
/companyAddress |
Company addresses |
UmsMemberLevelController |
/memberLevel |
Member levels |
OssController |
/aliyun/oss |
Aliyun OSS upload |
MinioController |
/minio |
MinIO upload |
mall-portal (port 8085)
| Controller | Base Path | Operations |
|---|---|---|
UmsMemberController |
/sso |
Login, register, info |
OmsCartItemController |
/cart |
Cart CRUD |
OmsPortalOrderController |
/order |
Place, cancel, list, pay |
OmsPortalOrderReturnApplyController |
/returnApply |
Submit return |
UmsMemberReceiveAddressController |
/member/address |
Address CRUD |
UmsMemberCouponController |
/member/coupon |
Coupon claim/list |
MemberAttentionController |
/member/attention |
Brand follow |
MemberProductCollectionController |
/member/productCollection |
Product collect |
MemberReadHistoryController |
/member/readHistory |
Browse history |
HomeController |
/home |
Homepage content |
PmsPortalBrandController |
/brand |
Brand browsing |
PmsPortalProductController |
/product |
Product detail/search |
AlipayController |
/alipay |
Payment integration |
mall-search (port 8081)
| Controller | Base Path | Operations |
|---|---|---|
EsProductController |
/esProduct |
Import, search, CRUD index |
Docker Commands Quick Reference
# Start all infrastructure
docker compose -f document/docker/docker-compose-env.yml up -d
# Start all application services
docker compose -f document/docker/docker-compose-app.yml up -d
# View logs for a specific container
docker logs -f mall-admin
# Restart a single service
docker restart mall-portal
# Check all container status
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
Build Commands
# Full build (skip tests)
mvn clean package -DskipTests
# Build single module
mvn clean package -DskipTests -pl mall-admin -am
# Run locally (dev profile)
java -jar mall-admin/target/mall-admin-1.0-SNAPSHOT.jar --spring.profiles.active=dev