项目:xyMall | 版本:v1.0 | 生成日期:2026-10-05 | 依据:源码分析
xyMall 是一个前后端分离的全品类电商系统(对标京东购物范式),仓库内含四个可独立构建的子项目:一个 Spring Boot 3 多模块后端(xy-mall/)与三个前端应用——PC 响应式商城(xy-mall-web/)、Element Plus 管理后台(xy-mall-admin/)、Vant 4 移动端 H5(xy-mall-h5/)。
根据 xy-mall/AGENTS.md 的定位描述,该系统是单实例部署的教学/演示级高完成度商城:一台服务器 + MySQL 8 + Redis(可选,Redis 挂掉自动降级纯 DB 路径,不阻断交易)。它刻意覆盖了电商领域的完整业务面——商品/SKU、购物车、订单状态机、四层优惠(券/满减/PLUS/积分)、支付(模拟支付、余额、支付宝沙箱)、秒杀(Redis Lua 预扣 + DB 权威扣减)、拼团、预售、售后退款、库存流水、RBAC 权限、操作审计、站内 IM 客服——并在关键链路上按大厂标准实现生产化能力(条件更新防超卖、幂等、延迟双删、对账纠偏、限流、分布式锁、可观测性)。因此它同时适合两类读者:
服务对象角色分为三类:消费者(商城 Web / H5 端的用户,可注册登录、浏览下单)、运营/管理员(管理后台的用户,管理商品、订单、营销与用户)、客服(后台 IM 控制台的使用者,通过 WebSocket 与消费者实时会话)。
从项目规模看,这是一套"麻雀虽小、五脏俱全"的系统:后端 xy-mall-server 含 30 个业务模块、50 余个 Controller,MySQL 侧由 Flyway V1~V8 迁移脚本定义了 40 张表(覆盖商品、订单、营销、秒杀、拼团、售后、IM 等完整业务面),配套 32 个单元/集成测试(7 个测试类,含 framework-core 的 CsvUtilTest)、xy-mall/scripts/load-seckill.py 秒杀压测脚本与前端 e2e GUI 冒烟脚本。仓库 mall/docs/ 目录还保留了完整的演进档案:HANDOVER.md 记录了十轮迭代交接,BIG-TECH-READINESS-ASSESSMENT.md 是对照大厂标准逐项打分的生产化自评,MICROSERVICE-SHARDING-PLAN.md 则是"未来若要拆微服务"的评估底稿(只评估、未实施)。这些档案与源码互相印证,是理解"代码为什么长这样"的第一手线索。
选择"电商"作为业务载体并非偶然:电商域天然覆盖了后端工程的大多数经典难题——库存并发正确性(超卖)、支付一致性(幂等与补偿)、营销规则的叠加计算(优惠分摊)、流量脉冲(秒杀)、缓存一致性(商品详情高读低写),且每个难题都有肉眼可判的对错标准(订单金额对不对、库存会不会为负)。把它做成一个可运行、可压测、可观测的小型系统,比抽象地讲概念更能暴露设计取舍。
以下功能均从源码模块与 Controller 提取验证:
| 功能域 | 功能点 | 主要代码位置(相对 mall/) |
|---|---|---|
| 用户账户 | 注册(验证码+注册赠券+可选赠余额)、登录、改密、资料修改、登出(token 黑名单)、注销账户 | xy-mall/.../modules/user/,xy-mall-web/src/views/LoginView.vue |
| 认证安全 | JWT + token_version 会话版本 + Redis token 黑名单 + 登录失败计数锁定 + 图形验证码 + 后台 IP 白名单 | xy-mall/framework/framework-core/.../security/,framework-cache/.../security/ |
| 商品中心 | 商品列表/搜索/联想/热卖榜/详情、三级分类、品牌筛选、SKU 规格、预售、多商户挂载 | xy-mall/.../modules/goods/、category/、search/ |
| 营销促销 | 优惠券(领取/兑换/注册赠)、满减活动、PLUS 会员折扣、积分签到与抵扣、拼团、秒杀 | coupon/、promotion/、plus/、groupbuy/、seckill/ |
| 交易订单 | 购物车、结算下单(幂等头)、四层优惠计算、订单状态机、取消/支付/确认收货、超时关单三重兜底 | cart/、order/(含 statemachine/OrderStateMachine) |
| 支付 | 模拟支付(dev 开关)、余额支付(条件扣款防透支)、支付宝沙箱(RSA2 验签 + 回调幂等 + 迟到支付补偿退款) | pay/(PayController、AlipayPayService) |
| 库存 | SKU/主表库存条件扣减、库存流水(stock_log)、低库存预警(StockAlertController) | stock/、goods/ |
| 物流售后 | 物流轨迹(演示数据)、拆单包裹、售后申请与后台审核退款 | order/、parcel/、aftersale/ |
| 用户互动 | 商品评价(追评/点赞/商家回复)、收藏、浏览足迹、"看完又看"推荐 | comment/、favorite/、user/(BrowseLog) |
| 消息与 IM | 站内消息(订单/物流/系统)、WebSocket 客服 IM(用户↔管理员,历史落库) | message/、im/(ImWebSocketHandler) |
| 管理后台 | 仪表盘(ECharts)、商品/分类/订单/用户/优惠券/秒杀/轮播/首页配置/满减/拼团/卖家/运营参数管理、管理员与 RBAC、操作审计日志、IM 工作台 | xy-mall/server/.../modules/admin/,xy-mall-admin/src/views/ |
| 基础设施 | 统一响应 R、全局异常、限流(IP/用户维度)、分布式锁、接口耗时观测(Prometheus + Grafana)、Flyway 迁移、图片上传(MinIO/本地 upload 回落) | xy-mall/framework/、db/migration/、modules/upload/ |
对这张表做一点阅读上的展开。交易主线(上半部分从用户账户到物流售后的连续各行)串起了一个消费者从注册到售后的完整购物旅程:注册即领券赠余额的"新人礼包"把新用户第一时间导入营销体系;商品中心以三级分类、品牌与 SKU 规格组织货品,搜索/联想/热卖榜/"看完又看"四种发现路径分别服务"目标明确、模糊意图、从众心理、兴趣延伸"四类购物心智;结算时四层优惠按"券→满减→积分→PLUS"固定顺序叠加计算,支付后订单进入状态机管理,超时未付由三重兜底关单并回补库存;确认收货后还能评价、追评、收藏,形成交易闭环。这条主线的端到端代码走读见《05-核心流程》。
支撑线(认证安全、消息与 IM、管理后台、基础设施)则回答"一个商城要稳稳跑起来还需要什么":JWT + 会话版本 + token 黑名单构成可随时吊销的登录态;站内消息覆盖订单、物流、系统三类事件通知;管理后台用 RBAC 把"谁能干什么"收敛为权限码并辅以操作审计留痕;基础设施层把限流、分布式锁、幂等、对账、可观测这些生产化能力做成 framework 通用件,业务模块按需取用而不必各自造轮子。各功能域的表结构与字段语义见《04-数据模型》,三端页面与组件组织见《02-页面设计》。
xy-mall/)| 类别 | 选型 | 版本 | 选型理由(依据 pom.xml 与源码注释) |
|---|---|---|---|
| 语言/JDK | Java | 17 | 父 POM xy-mall/pom.xml 固定 java.version=17,配套 Spring Boot 3 基线 |
| 核心框架 | Spring Boot | 3.4.13 | 单体内聚、起步依赖与自动装配,降低教学复杂度 |
| ORM | MyBatis-Plus | 3.5.9 | 在 MyBatis 之上提供 lambda 条件构造器、分页插件、逻辑删除与审计字段填充,framework-orm 统一装配 |
| 数据库 | MySQL | 8(驱动 8.4.0) | 事务与条件更新(CAS)是本系统防超卖的权威闸门 |
| 连接池 | Druid | 1.2.25 | 自带 SQL 监控/慢 SQL 日志(slow-sql-millis: 2000),且按安全要求关闭了 Web 监控台 |
| 缓存/队列 | Redis(Spring Data Redis + StringRedisTemplate) | 7.x(部署侧) | 商品缓存、秒杀 Lua 预扣、延迟队列(ZSet)、分布式锁、token 黑名单、验证码存储 |
| 迁移 | Flyway | 随 Boot BOM | schema 变更只走 db/migration/V1~V8,validate-on-migrate: true 防止代码超前于迁移 |
| 安全 | jjwt(HS256)+ 加盐 MD5 | 0.12.6 | framework-core/.../security/JwtUtil.java、PasswordUtil.java |
| API 文档 | SpringDoc OpenAPI + Knife4j | 2.6.0 / 4.5.0 | /doc.html 在线调试,prod profile 关闭 |
| 对象存储 | MinIO(S3 兼容,可选) | - | 商品图上传,密钥缺失或 NAS 掉线自动回落本地 upload/ 目录 |
| 工具库 | Lombok / MapStruct / Hutool / Fastjson2 / Guava | - | 消除样板代码、VO 转换、通用工具。注:除 Lombok 外,MapStruct/Hutool/Fastjson2/Guava(及 commons-lang3/collections4/io)当前源码零 import、可整批移除,见《17-依赖全景》§5.2 |
| 可观测 | Actuator + Micrometer + Prometheus + Grafana | - | management.endpoints...include: health,info,prometheus,Grafana 面板见 xy-mall/deploy/grafana/ |
| 维度 | xy-mall-web(商城 PC) | xy-mall-admin(管理后台) | xy-mall-h5(移动端) |
|---|---|---|---|
| UI 库 | Element Plus 2.9(响应式适配手机) | Element Plus 2.9 | Vant 4.9 |
| 图表/富文本 | - | ECharts 6、wangEditor 5 | - |
| 状态管理 | Pinia 2.3 | Pinia 2.3 | Pinia 3.0 |
| 路由 | Vue Router 4.5(history 模式) | 同左 | 同左 |
| HTTP | axios 1.7(/api baseURL + 拦截器) | 同左(blob 导出放宽超时) | 同左 |
| dev 端口 | 5177 | 5176 | 5188 |
| 特殊依赖 | element-china-area-data(省市区) | - | - |
| 包管理 | pnpm 11(packageManager 字段锁定) | pnpm 11 | pnpm 11 |
选型理由:三端共用同一套 Vue 3 技术心智与同一种 axios 封装(src/api/request.ts 几乎同构),后端统一响应 R{code,message,data} 使三端能以同一种方式解包数据;Element Plus 承担后台密集的表格/表单场景,Vant 4 则为移动端提供触摸友好的组件;ECharts 按需注册(DashboardView.vue 中 echarts.use([...]))控制产物体积。
几处值得注意的选型权衡:其一,后端坚持"单体内多模块"而非微服务——30 个模块同进程部署,换来极低的运维成本与事务内一致性(下单扣库存、核销券、扣积分在同一事务内完成),代价是登录失败计数、幂等键、sys_config 进程缓存等进程内状态无法直接横向扩容,《MICROSERVICE-SHARDING-PLAN.md》评估过拆分路径但刻意不实施;其二,Redis 被定位为"可丢的增强层"而非硬依赖——缓存、预扣库存、延迟队列、分布式锁全部 try/catch 降级,最坏情况系统退化为纯 DB 路径,牺牲吞吐但不牺牲正确性,这使教学环境"不装 Redis 也能跑通全部业务";其三,框架层五个 Maven 模块刻意做到可独立复用(framework-core 甚至零 Spring Web 依赖),为将来抽取公共脚手架留了口子;其四,金额一律以"分"(INT)存储、schema 变更只走 Flyway,分别消除了浮点精度与"库结构漂移"两类高频事故源。
mall/
├── xy-mall/ # 后端单体(Spring Boot 3 多模块,端口 8081)
│ ├── pom.xml # 父 POM:版本仲裁(dependencyManagement)
│ ├── framework/ # 通用框架层(五个子模块,均可独立复用)
│ │ ├── framework-core/ # R 统一响应、BizException、JWT/加盐MD5、@LoginUser、常量、CsvUtil(零 Spring Web 依赖)
│ │ ├── framework-web/ # 全局异常、RateLimitFilter、@RateLimiter 切面、WebLogAspect、@LoginUser 解析器、CORS、/upload 静态映射
│ │ ├── framework-orm/ # MybatisPlusConfig(分页)、XyMetaObjectHandler(审计字段填充)
│ │ ├── framework-cache/ # RedisTemplate 装配、@DistributeLock 注解式分布式锁、验证码/登录失败/Token黑名单的 Redis 实现
│ │ └── framework-swagger2/ # OpenApiConfig(SpringDoc + Knife4j)
│ ├── server/ # 业务服务 xy-mall-server(启动类 XyMallServerLauncher)
│ │ └── src/main/java/com/xiaoye/mall/server/
│ │ ├── XyMallServerLauncher.java
│ │ └── modules/ # 30 个业务模块 × {controller|service|mapper|entity|vo|context|job|aop|ws} 分层
│ │ ├── user/ cart/ order/ pay/ goods/ category/ seckill/ coupon/ promotion/
│ │ ├── plus/ groupbuy/ aftersale/ parcel/ comment/ favorite/ address/
│ │ ├── message/ im/ search/ es/ stock/ seller/ admin/ config/ upload/
│ │ └── index/ indexConfig/ carousel/ captcha/ health/
│ └── server/src/main/resources/
│ ├── application.yml # 主配置(数据源/Redis/JWT/支付/OSS/CORS)
│ ├── application-dev.yml # dev:SQL 打印、验证码旁路 0000
│ ├── application-prod.yml # prod:关文档/CORS 收紧/actuator 收紧
│ ├── db/migration/V1~V8.sql # Flyway 版本化迁移(建表与种子数据)
│ └── sql/archive/ # 历史手工脚本归档(已被 Flyway 取代)
│ ├── distribution/ # 打包分发模块
│ ├── Dockerfile # maven 构建 → temurin JRE 运行
│ ├── docker-compose.yml # mysql+redis+backend+admin-web+mall-web 一键编排
│ ├── deploy/ # prometheus.yml、grafana 面板、nginx-https 示例
│ ├── scripts/ # db-backup.sh、e2e-smoke.py、load-seckill.py 压测
│ ├── start.sh # 读取 .env.properties 后 java -jar 启动
│ └── AGENTS.md / README.md # 项目上下文与快速开始
├── xy-mall-web/ # PC 商城前端(5177)
│ └── src/
│ ├── api/ # request.ts(axios 封装)+ index.ts(~70 个接口函数)
│ ├── router/index.ts # 17 条路由 + 登录白名单守卫
│ ├── stores/user.ts # Pinia:token/userInfo 持久化 localStorage
│ ├── composables/ # useCartCount、usePublicConfig
│ ├── components/ # AppHeader/AppFooter/GoodsCard/GoodsSkeleton/ImWidget/ServiceBar
│ ├── views/ # 17 个页面视图(Home/GoodsDetail/Checkout/OrderList/Seckill...)
│ └── styles/ # reset/variables/global(768px 断点响应式)
├── xy-mall-admin/ # 管理后台(5176)
│ └── src/
│ ├── api/ # ~90 个 admin 接口函数(/api/admin/**)
│ ├── router/index.ts # Layout 嵌套路由,meta.perm 权限点
│ ├── directives/perm.ts # v-perm 按钮级权限指令
│ ├── views/ # Layout + 19 个业务页面(GoodsListView、OrderListView、DashboardView...)
│ └── utils/ # download.ts(CSV 导出)、img.ts
├── xy-mall-h5/ # 移动端 H5(5188,迭代中)
│ └── src/
│ ├── api/index.ts # 精简版接口(认证/商品/购物车/订单/资产)
│ ├── router/index.ts # 9 条路由 + van-tabbar 四个底部页签
│ └── views/ # Home/Category/List/Detail/Cart/Checkout/Orders/Profile/Login
└── docs/ # 项目历史文档(HANDOVER 十轮交接、需求 backlog、就绪度自评等)这份目录有几个设计意图值得点出:framework/ 与 server/ 的拆分是"平台件 vs 业务件"的边界,前者不感知任何业务语义(验证码存储、登录失败计数都是抽象接口加双实现),后者只做业务编排;server/modules/ 下 30 个模块采用完全同构的分层骨架(controller/service/mapper/entity/vo/context,复杂模块另有 job/aop/ws),新模块照抄一个现有模块即可上手;三端前端的 api/request.ts 封装与 Pinia store 命名保持一致,读者在任意一端建立的认知可平移到另外两端;db/migration/ 与 sql/archive/ 并存则展示了"Flyway 取代手工脚本"的规范落地方式——archive 里的旧脚本只作历史归档,不再执行。
以下命令即可在本机把后端与 PC 商城跑起来(完整细节见第 06 篇):
# 1. 初始化数据库(需本地 MySQL,root/root1234 供集成测试使用)
mysql -u root -p < xy-mall/server/src/main/resources/db/migration/V1__init.sql
# —— 或直接空库启动:Flyway baseline-on-migrate=true 会自动建表
# 2. 注入必填 JWT 密钥(无默认值,缺失时启动直接失败)
cd xy-mall
export XY_MALL_JWT_SECRET=$(openssl rand -base64 36)
export MYSQL_USERNAME=root MYSQL_PASSWORD=你的密码
# 3. 编译并启动后端(必须以 xy-mall/ 为工作目录,/upload/** 静态映射是相对路径)
mvn clean install -DskipTests
mvn -pl server spring-boot:run
# 健康检查:curl http://localhost:8081/api/health
# 接口文档:http://localhost:8081/doc.html
# 4. 启动 PC 商城(另开终端)
cd xy-mall-web && pnpm install && ./node_modules/.bin/vite # http://localhost:5177
# 5. 启动管理后台 / H5
cd xy-mall-admin && ./node_modules/.bin/vite # http://localhost:5176
cd xy-mall-h5 && ./node_modules/.bin/vite # http://localhost:5188关键开发约定(源自 xy-mall/README.md 与 AGENTS.md,全文档集将反复引用):
com.xiaoye.mall.server.modules.{module}.{layer},复杂入参聚合为 XxxContext,VO 转换按 README/AGENTS 约定"交给 MapStruct converter"——但当前源码零 converter 实现,实际用 BeanUtils.copyProperties(见《17-依赖全景》§5.2);BizException,由 framework-web 的 GlobalExceptionHandler 转为 R{code,message};/api/**,管理端 /api/admin/**;请求头 Authorization: Bearer <token>;--mall.captcha.allow-bypass=true 启动后验证码填 0000。另有两个新手高频踩坑点提前提示:一是前端 dev 需以 ./node_modules/.bin/vite 直跑(pnpm 11 的构建脚本拦截所致),且前端默认仅监听 IPv6,请用 localhost 而非 127.0.0.1 访问;二是后端必须以 xy-mall/ 为工作目录启动,否则 /upload/** 相对路径映射丢失、商品图全部 404。生产环境变量清单与 Docker/nginx 编排见第 06 篇。
本套文档共 7 篇,建议按 00 → 01 → 04 → 03 → 02 → 05 → 06 的顺序阅读:先建立全局认知(00/01),再理解数据底座(04)与对外契约(03),随后深入三端页面(02)与端到端业务流程(05),最后按 06 部署运行。每篇均引用真实源码相对路径(相对 mall/ 目录),读者可随时对照源码验证。
也可以按角色取用:准备面试的读者建议 00 → 01 → 05(秒杀三级漏斗、超时关单三重兜底、缓存延迟双删是高频考点)→ 08(安全与权限);接手开发的读者建议 00 → 01 → 04 → 03 → 02,再以《07-模块详解》当模块级字典随手查;负责部署运维的读者可直接 06 → 14(配置与环境详解)→ 12(FAQ 与故障排查)。文档集以源码为唯一事实来源,遇到文档与源码不一致处,以源码为准。