mall4cloud Documentation

️⭐️⭐️微服务商城系统 springcloud微服务商城 小程序商城

6,162 stars JavaScript JavaScript 43 files · ~17,146 tokens #java#mall#springboot4#springcloud#vue3
RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy mall4cloud on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name mall4cloud -p 8180:8180 --restart always registry.cn-hongkong.aliyuncs.com/mall4j-images/mysql:8.0.35
Configured Services & Ports
⚙️ mall4cloud-mysql
image: registry.cn-hongkong.aliyuncs.com/mall4j-images/mysql:8.0.35
⚙️ mall4cloud-minio
image: registry.cn-hongkong.aliyuncs.com/mall4j-images/minio:RELEASE.2024-04-18T19-09-19Z
⚙️ mall4cloud-redis
image: registry.cn-hongkong.aliyuncs.com/mall4j-images/redis:7.0
⚙️ mall4cloud-nacos
image: registry.cn-hongkong.aliyuncs.com/mall4j-images/nacos-server:v3.1.1
⚙️ mall4cloud-seata
image: registry.cn-hongkong.aliyuncs.com/mall4j-images/seata-server:2.6.0
⚙️ mall4cloud-elasticsearch
image: registry.cn-hongkong.aliyuncs.com/mall4j-images/elasticsearch:7.17.21
⚙️ mall4cloud-canal
image: registry.cn-hongkong.aliyuncs.com/mall4j-images/canal-server:v1.1.7
⚙️ mall4cloud-rocketmq-namesrv
image: registry.cn-hongkong.aliyuncs.com/mall4j-images/rocketmq:5.2.0
⚙️ mall4cloud-rocketmq-broker
image: registry.cn-hongkong.aliyuncs.com/mall4j-images/rocketmq:5.2.0
⚙️ mall4cloud-rocketmq-dashboard
image: registry.cn-hongkong.aliyuncs.com/mall4j-images/rocketmq-dashboard:1.0.1
🔌 Ports: 8180:8082
docker-compose.yml
yaml (docker-compose.yml)
version: "3.5"

services:
  mall4cloud-mysql:
    image: registry.cn-hongkong.aliyuncs.com/mall4j-images/mysql:8.0.35
    container_name: mall4cloud-mysql
    restart: always
    environment:
      - MYSQL_ROOT_PASSWORD=80jpnH4.r5g
    network_mode: "host"
    expose:
      - 3306
    volumes:
      - ./mysql/data:/var/lib/mysql
      - ./mysql/conf.d:/etc/mysql/conf.d
      - ./mysql/initdb:/docker-entrypoint-initdb.d

  mall4cloud-minio:
    image: registry.cn-hongkong.aliyuncs.com/mall4j-images/minio:RELEASE.2024-04-18T19-09-19Z
    container_name: mall4cloud-minio
    restart: always
    command: server /data --console-address ":9001"
    network_mode: "host"
    expose:
      - 9000
      - 9001
    volumes:
      - ./minio/data:/data
    environment:
      - MINIO_ROOT_USER=admin
      - MINIO_ROOT_PASSWORD=80jpnH4.r5g
      - MINIO_BROWSER_REDIRECT_URL=http://192.168.1.46:9001

  mall4cloud-redis:
    image: registry.cn-hongkong.aliyuncs.com/mall4j-images/redis:7.0
    container_name: mall4cloud-redis
    restart: always
    network_mode: "host"
    command: redis-server --requirepass 80jpnH4.r5g
    expose:
      - 6379


  mall4cloud-nacos:
    image: registry.cn-hongkong.aliyuncs.com/mall4j-images/nacos-server:v3.1.1
    container_name: mall4cloud-nacos
    restart: always
    depends_on:
      - mall4cloud-mysql
    network_mode: "host"
    expose:
      - 8848
      - 9848
      - 9849
      - 8080
    environment:
      - JVM_XMS=256m
      - JVM_XMX=256m
      - MODE=standalone
      - PREFER_HOST_MODE=hostname
      - SPRING_DATASOURCE_PLATFORM=mysql
      - MYSQL_SERVICE_HOST=192.168.1.46
      - MYSQL_SERVICE_DB_NAME=mall4cloud_nacos
      - MYSQL_SERVICE_USER=root
      - MYSQL_SERVICE_PASSWORD=80jpnH4.r5g
      - NACOS_AUTH_ENABLE=true
      - NACOS_AUTH_TOKEN=TWFsbDRqTWFsbDRjbG91ZE1hbGw0ak1hbGw0Y2xvdWRNYWxsNGpNYWxsNGNsb3Vk
      - NACOS_AUTH_IDENTITY_KEY=mall4jmall4jmall4jmall4jmall4jmall4jmall4jmall4j
      - NACOS_AUTH_IDENTITY_VALUE=mall4cloudmall4cloudmall4cloudmall4cloudmall4cloudmall4cloudmall4cloud
    volumes:
      - ./nacos/logs:/home/nacos/logs

  mall4cloud-seata:
    image: registry.cn-hongkong.aliyuncs.com/mall4j-images/seata-server:2.6.0
    container_name: mall4cloud-seata
    restart: always
    network_mode: "host"
    expose:
      - 8091
    environment:
      - TZ
      - STORE_MODE=db
      - SEATA_IP=192.168.1.46
      - SEATA_PORT=8091
    volumes:
      - ./seata/application.yml:/seata-server/resources/application.yml

  mall4cloud-elasticsearch:
    image: registry.cn-hongkong.aliyuncs.com/mall4j-images/elasticsearch:7.17.21
    container_name: mall4cloud-elasticsearch
    restart: always
    network_mode: "host"
    expose:
      - 9200
      - 9300
    environment:
      - discovery.type=single-node
      - ES_JAVA_OPTS=-Xms512m -Xmx512m
      - ELASTICSEARCH_USERNAME=elastic
      - ELASTIC_PASSWORD=80jpnH4.r5g
      - xpack.security.enabled=true
    volumes:
      - ./elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
      - ./elasticsearch/data:/usr/share/elasticsearch/data
      - ./elasticsearch/plugins:/usr/share/elasticsearch/plugins

  mall4cloud-canal:
    image: registry.cn-hongkong.aliyuncs.com/mall4j-images/canal-server:v1.1.7
    container_name: mall4cloud-canal
    restart: always
    network_mode: "host"
    expose:
      - 11111
    volumes:
      - ./canal/conf/example:/home/admin/canal-server/conf/example
      - ./canal/conf/canal.properties:/home/admin/canal-server/conf/canal.properties
      - ./canal/logs:/home/admin/canal-server/logs


  mall4cloud-rocketmq-namesrv:
    image: registry.cn-hongkong.aliyuncs.com/mall4j-images/rocketmq:5.2.0
    container_name: mall4cloud-rocketmq-namesrv
    restart: always
    network_mode: "host"
    expose:
      - 9876
    volumes:
      - ./rocketmq/namesrv/logs:/home/rocketmq/logs
      - ./rocketmq/namesrv/store:/home/rocketmq/store
    environment:
      JAVA_OPT_EXT: "-Duser.home=/home/rocketmq -Xms512M -Xmx512M -Xmn128M"
    command: ["sh","mqnamesrv"]

  mall4cloud-rocketmq-broker:
    image: registry.cn-hongkong.aliyuncs.com/mall4j-images/rocketmq:5.2.0
    container_name: mall4cloud-rocketmq-broker
    restart: always
    network_mode: "host"
    expose:
      - 10909
      - 10911
    volumes:
      - ./rocketmq/broker/logs:/home/rocketmq/logs
      - ./rocketmq/broker/store:/home/rocketmq/store
      - ./rocketmq/broker/conf/broker.conf:/etc/rocketmq/broker.conf
    environment:
      JAVA_OPT_EXT: "-Duser.home=/home/rocketmq -Xms512M -Xmx512M -Xmn128M -XX:-AssumeMP"
    command: ["sh","mqbroker","-c","/etc/rocketmq/broker.conf","-n","192.168.1.46:9876","autoCreateTopicEnable=true"]
    depends_on:
      - mall4cloud-rocketmq-namesrv


  mall4cloud-rocketmq-dashboard:
    image: registry.cn-hongkong.aliyuncs.com/mall4j-images/rocketmq-dashboard:1.0.1
    container_name: mall4cloud-rocketmq-dashboard
    restart: always
    ports:
      - 8180:8082
    environment:
      JAVA_OPTS: "-Drocketmq.namesrv.addr=192.168.1.46:9876 -Dcom.rocketmq.sendMessageWithVIPChannel=false"
    depends_on:
      - mall4cloud-rocketmq-namesrv

Technical Documentation: gz-yami/mall4cloud

ℹ️ Provenance: Multi-Tier Ingestion · CodeWiki Reference

Overview (`README.md`)

Mall4cloud 开源版微服务商城系统

Mall4cloud 是 Mall4j 体系下的微服务商城产品线。本仓库是 Mall4cloud 开源版主仓库,开源版面向 B2B2C 商城架构,基于 Spring Boot 4、Spring Cloud、Nacos、Seata、MySQL、Redis、RocketMQ、Canal、Elasticsearch、MinIO 等组件构建,包含平台端、商家端、用户端和完整订单流程,适合学习微服务电商架构、评估多商户商城源码,以及进行企业商城系统二次开发。

项目说明

  • 项目名称:Mall4cloud 微服务商城开源版、Mall4cloud B2B2C 开源商城、Mall4j 微服务商城开源仓库。
  • 项目简介:Mall4cloud 是 Mall4j 体系下的微服务商城产品线;本仓库是 Mall4cloud 开源版主仓库,开源版面向 B2B2C 商城架构,适合学习微服务电商架构、评估多商户商城源码和企业商城二次开发。
  • 技术说明:Mall4cloud 主线已升级到 Spring Boot 4、Spring Cloud 和 Vue3,具体依赖版本以后端 pom.xml 和前端 package.json 为准。
  • 开源授权:本仓库开源版遵守 AGPLv3 协议,适合学习、评估和符合协议的使用场景。
  • 商业授权:闭源商用、企业私有化交付、微服务集群交付、企业级售后和更多业务版本应参考 Mall4j 官网商业授权说明。
  • 企业版本:商业版坚持 100% 源码交付、源码无加密、永久授权;付费企业版本覆盖 B2C、B2B2C、S2B2C、B2B2B、SaaS、多租户、跨境等场景,具体功能和服务范围以官网与合同确认为准。
  • 版本说明:Mall4cloud 是 Mall4j 体系下的微服务商城产品线,区别于 Mall4j 单体开源版;企业版本的功能和服务以官网说明为准。
  • 相关链接:官网、价格/功能对比、客户案例、当前仓库。

项目特点

  • Spring Boot 4 + Spring Cloud 微服务架构
  • Nacos 服务注册与配置,Seata 分布式事务
  • Redis 缓存、RocketMQ 消息队列、Elasticsearch 搜索、MinIO 文件存储
  • 平台端、商家端、用户端、多服务模块协同
  • AGPLv3 开源,商业授权和企业版本说明见“授权与版本”

技术版本说明

Mall4cloud 主线已升级到 Spring Boot 4、Spring Cloud 和 Vue3,适合微服务商城新项目评估和长期维护。对于仍停留在旧技术栈上的商城系统,后续框架升级、依赖兼容和安全维护成本通常更高;本项目的具体依赖版本以后端 pom.xml 和前端 package.json 为准。

前言

本仓库致力于提供一个功能完整、易于维护的 Mall4cloud 开源版微服务电商系统参考实现。当前开源版面向 B2B2C 商城架构,后台管理系统包含平台管理、店铺管理、商品管理、订单管理、规格管理、权限管理、资源管理等模块。Mall4j 体系下更多版本和功能范围以官网说明为准。

文档与快速启动

项目文档位于仓库 doc 目录,也可以通过以下链接查看:

建议先阅读文档,再结合视频搭建本地开发环境。先起启动中间件 MySQL、Redis、Nacos、MinIO;后端最小链路是网关 mall4cloud-gateway(8000)+ auth + rbac + biz + 平台端 platform 或商家端 multishop。前端 VITE_APP_BASE_API 只配网关,不要直连业务端口。

项目按阿里巴巴代码规约进行检查,以下是代码规约扫描结果:

具体目录结构和二次开发阅读路径,可以查看 技术文档。

授权与版本

本仓库开源版使用 AGPLv3 协议。你可以按协议学习、研究、二次开发和自行部署。

闭源商用、企业私有化部署交付、微服务集群部署支持、100% 源码交付、源码无加密、永久授权、供应链/SaaS/跨境版本、演示环境和企业级售后支持属于商业授权或企业版本范围,可以通过 Mall4j 官网了解。

商业授权支持

开源版与企业版本

对比项 开源版 企业版本
学习微服务电商架构 支持 支持
授权方式 AGPLv3 开源协议 商业授权
闭源商用 需另行取得商业授权 按商业授权使用
部署方式 可自行部署(遵循 AGPLv3) 可提供企业私有化部署交付服务
仓库/版本定位 Mall4cloud 开源版主仓库,面向微服务 B2B2C 商城架构 Mall4j/Mall4cloud 企业版本体系,不等同于本开源仓库的增强版
版本范围 微服务 B2B2C 开源架构与基础业务能力 可覆盖 B2C、B2B2C、S2B2C、B2B2B、SaaS、多租户、跨境等版本
100% 源码交付、源码无加密、永久授权 可获取当前开源代码,不等同商业交付承诺 商业版支持,具体以官网和合同为准
企业级售后支持 社区交流为主 可提供商业支持

常见问题

Mall4cloud 是什么?

Mall4cloud 是 Mall4j 体系下的微服务商城产品线。本仓库是 Mall4cloud 开源版主仓库,开源版面向 B2B2C 商城架构,基于 Spring Boot 4、Spring Cloud、Nacos、Seata、Redis、RocketMQ、Elasticsearch、MinIO 等组件构建。

Mall4cloud 和 Mall4j 有什么区别?

Mall4j 开源版主仓库更适合了解 Java 单体商城和 B2C 单商户基础能力;Mall4cloud 开源版主仓库面向微服务 B2B2C 商城架构,包含平台端、商家端、用户端和多个后端服务模块。

Mall4cloud 是否适合企业私有化部署?

开源版可以按 AGPLv3 协议自行部署和评估。

闭源商用、企业私有化交付、集群部署支持、长期售后和更多业务版本,可以通过 Mall4j 官网了解企业版本。

前端应该连哪个端口?

管理后台和 uni-app 都只连网关 8000。auth、rbac、product 等业务服务有各自端口,用于本机启动和注册 Nacos,不要配进 VITE_APP_BASE_API。

仓库示例 IP 是 192.168.1.46,拿到源码后请批量替换成自己的地址。

Mall4cloud 是否已经升级到 Spring Boot 4?

Mall4cloud 主线已升级到 Spring Boot 4,具体依赖版本以后端 pom.xml 和前端 package.json 为准。

相关资料

相关开源仓库

仓库 说明
mall4cloud Mall4cloud 开源版 Java 微服务后端主仓库,面向 B2B2C 架构
mall4cloud-platform 平台端管理后台,默认账号 admin,密码 123456
mall4cloud-multishop 商家端管理后台,默认账号 admin,密码 123456
mall4cloud-uniapp uni-app 用户端
mall4j Mall4j 开源版主仓库,面向 B2C 单商户商城

演示地址

演示地址:

pc端:https://cloud-pc.mall4j.com

H5端:https://h5.mall4j.com/cloud

小程序演示

目录结构规范

我们也有自己的目录结构

  • VO(View Object):显示层对象,通常是 Web 向模板渲染引擎层传输的对象。
  • DTO(Data Transfer Object):数据传输对象,前端像后台进行传输的对象,类似于param。
  • BO(Business Object):业务对象,内部业务对象,只在内部传递,不对外进行传递。
  • Model:模型层,此对象与数据库表结构一一对应,通过 Mapper 层向上传输数据源对象。
  • Controller:主要是对外部访问控制进行转发,各类基本参数校验,或者不复用的业务简单处理等。为了简单起见,一些与事务无关的代码也在这里编写。
  • FeignClient:由于微服务之间存在互相调用,这里是内部请求的接口。
  • Controller:主要是对内部访问控制进行转发,各类基本参数校验,或者不复用的业务简单处理等。为了简单起见,一些与事务无关的代码也在这里编写。
  • Service 层:相对具体的业务逻辑服务层。
  • Manager 层:通用业务处理层,它有如下特征:
    • 1) 对第三方平台封装的层,预处理返回结果及转化异常信息,适配上层接口。
    • 2) 对 Service 层通用能力的下沉,如缓存方案、中间件通用处理。
    • 3) 与 DAO 层交互,对多个 DAO 的组合复用。
  • Mapper持久层:数据访问层,与底层 MySQL进行数据交互。
  • Listener:监听 RocketMQ 进行处理,有时候会监听easyexcel相关数据。

关于FeignClient,由于微服务之间存在互相调用,Feign 是http协议,理论上是为了解耦,而实际上提供方接口进行修改,调用方却没有进行修改的时候,会造成异常,所以我们抽取出来。还有就是对内暴露的接口,是很多地方都公用的,所以我们还将接口抽取了出了一个模块,方便引用。可以看到mall4cloud-api这个模块下是所有对内feign接口的信息。

目录结构

text
mall4cloud
├─mall4cloud-api -- 内网接口
│  ├─mall4cloud-api-auth  -- 授权对内接口
│  ├─mall4cloud-api-biz  -- biz对内接口
│  ├─mall4cloud-api-leaf  -- 美团分布式id生成接口
│  ├─mall4cloud-api-multishop  -- 店铺对内接口
│  ├─mall4cloud-api-order  -- 订单对内接口
│  ├─mall4cloud-api-platform  -- 平台对内接口
│  ├─mall4cloud-api-product  -- 商品对内接口
│  ├─mall4cloud-api-rbac  -- 用户角色权限对内接口
│  ├─mall4cloud-api-search  -- 搜索对内接口
│  └─mall4cloud-api-user  -- 用户对内接口
├─mall4cloud-auth  -- 授权校验模块
├─mall4cloud-biz  -- mall4cloud 业务代码。如图片上传/短信等
├─mall4cloud-common -- 一些公共的方法
│  ├─mall4cloud-common-cache  -- 缓存相关公共代码
│  ├─mall4cloud-common-core  -- 公共模块核心(公共中的公共代码)
│  ├─mall4cloud-common-database  -- 数据库连接相关公共代码
│  ├─mall4cloud-common-order  -- 订单相关公共代码
│  ├─mall4cloud-common-product  -- 商品相关公共代码
│  ├─mall4cloud-common-rocketmq  -- rocketmq相关公共代码
│  └─mall4cloud-common-security  -- 安全相关公共代码
├─mall4cloud-gateway  -- 网关
├─mall4cloud-leaf  -- 基于美团leaf的生成id服务
├─mall4cloud-multishop  -- 商家端
├─mall4cloud-order  -- 订单服务
├─mall4cloud-payment  -- 支付服务
├─mall4cloud-platform  -- 平台端
├─mall4cloud-product  -- 商品服务
├─mall4cloud-rbac  -- 用户角色权限模块
├─mall4cloud-search  -- 搜索模块
└─mall4cloud-user  -- 用户服务

商城部署后 API 地址

服务 地址
mall4cloud-gatway 网关服务 http://127.0.0.1:8000
mall4cloud-auth 授权校验服务 http://127.0.0.1:9101
mall4cloud-biz 业务代码服务(如图片上传/短信等) http://127.0.0.1:9000
mall4cloud-leaf 基于美团leaf的生成id服务 http://127.0.0.1:9100
mall4cloud-multishop 商家服务 http://127.0.0.1:9103
mall4cloud-order 订单服务 http://127.0.0.1:9106
mall4cloud-payment 支付服务 http://127.0.0.1:9113
mall4cloud-product 商品服务 http://127.0.0.1:9104
mall4cloud-rbac 用户角色服务 http://127.0.0.1:9102
mall4cloud-search 搜索服务 http://127.0.0.1:9108
mall4cloud-user 用户服务 http://127.0.0.1:9105

部署教程

部署教程请参考 环境搭建 和 中间件 Docker Compose。

代码运行相关截图

1.后台截图

  • 平台端

  • 商家端

2.小程序截图

3.uni-app截图

提交反馈

支持项目

如果这个项目对你有帮助,欢迎 Star、Fork 和提交 Issue。


Overview (`doc/README.md`)

Mall4cloud 技术文档

用 Cursor、Codex 或 Claude Code 打开本仓库时,可使用内置 Skill:.agents/skills/mall4cloud/(Claude Code 为 .claude/skills/mall4cloud/,内容相同)。它按开源版现有功能点辅助启动、使用和二次开发,详细说明仍以本 doc/ 目录为准。不要套用 Mall4j 单体仓库的模块和端口。

这里是 Mall4cloud 开源版的技术文档入口。按下面顺序阅读:先跑起来,再理解结构,最后做一个后台管理二开练习。

阅读路径

目标 阅读顺序 验收结果
30 分钟跑起基础链路 环境搭建 -> 中间件 Docker Compose -> 故障排查 网关、后端服务、平台端或商家端能登录
2 小时读懂系统结构 项目概览 -> 技术框架 -> 技术实现 -> 数据模型 能说清服务、前端、权限、数据库的请求链路
1 天完成简单二开 数据模型 -> 权限体系 -> 二次开发 能按现有模式写一个后台管理功能

一级目录

  1. 项目概览
  2. 环境搭建
  3. 技术框架
  4. 技术实现
  5. 二次开发
  6. 核心业务
  7. 数据模型
  8. 部署运维
  9. 故障排查

学习方式

检查题采用“题目 + 答案 + 原因”。阅读时先看结论,再打开对应代码、配置或 SQL 核对一次。


Overview (`doc/1-项目概览/README.md`)

项目概览

先用这部分建立全局地图:Mall4cloud 是什么、先看什么、每个模块负责什么。

阅读顺序

  1. 项目定位与阅读路径
  2. 模块职责地图
  3. 学习与自检

读完后,你应该能判断自己接下来要进入环境搭建、技术框架、数据模型还是二次开发。


Overview (`doc/2-环境搭建/README.md`)

环境搭建

这部分只服务一个目标:尽快跑起后端网关、必要服务和一个管理后台。

阅读顺序

  1. 环境要求
  2. 数据库初始化
  3. 后端启动
  4. 管理后台启动
  5. 移动端接口地址

中间件用 Docker Compose 时,直接看 部署运维/中间件 Docker Compose。


Overview (`doc/3-技术框架/README.md`)

技术框架

这部分解释项目骨架。先知道代码放哪里、请求怎么走、前后端如何对应。

阅读顺序

  1. 后端分层与模块
  2. 前端工程与动态路由

权限和分页等具体机制在 技术实现。


Overview (`doc/4-技术实现/README.md`)

技术实现

这部分讲二开最常碰到的机制:权限、上传、分页、验证、异常、消息和搜索。

阅读顺序

  1. 登录认证与权限链路
  2. 文件上传与富文本安全
  3. 分页、验证、异常与事务
  4. 消息、搜索与库存链路

Overview (`doc/5-二次开发/README.md`)

二次开发

这部分用一个后台管理功能示例,演示项目现有开发模式。

阅读顺序

  1. 后台管理功能二开示例
  2. 命名约定与验收清单

示例只写教程,不在仓库里新增业务代码。开始前先读 权限链路 和 核心表速查。


Overview (`doc/6-核心业务/README.md`)

核心业务

本目录只写业务阅读路线,不展开订单、支付、库存等高风险链路的改造教程。

阅读顺序

  1. 商品、订单、库存阅读路线

业务表的结构解释在 数据模型。


Overview (`doc/7-数据模型/README.md`)

数据模型

跑起来之后,先读数据库。权限、商品 SKU、订单结算相关表决定了登录、菜单、商品展示、下单和二开的基础理解。

阅读顺序

  1. 数据库阅读路线
  2. 权限、商品、订单核心表速查
  3. 带答案的表结构检查题

Overview (`doc/8-部署运维/README.md`)

部署运维

这部分区分本地启动、中间件一键部署、生产配置和上线检查。没有确认过的配置会列为待核对项。

阅读顺序

  1. 部署路径与上线检查
  2. 中间件 Docker Compose
  3. 已知风险与待核对项

Overview (`doc/9-故障排查/README.md`)

故障排查

这部分优先覆盖新读者第一次启动最常遇到的问题。

阅读顺序

  1. 启动、登录、接口常见问题

Overview (`front-end/mall4cloud-multishop/README.md`)

README

前言

本商城是基于Spring Cloud、Nacos、Seata、Mysql、Redis、RocketMQ、canal、ElasticSearch、minio的微服务B2B2C电商商城系统,采用主流的互联网技术架构、全新的UI设计、支持集群部署、服务注册和发现以及拥有完整的订单流程等,代码完全开源,没有任何二次封装,是一个非常适合二次开发的电商平台系统。

本商城致力于为中大型企业打造一个功能完整、易于维护的微服务B2B2C电商商城系统,采用主流微服务技术实现。后台管理系统包含平台管理,店铺管理、商品管理、订单管理、规格管理、权限管理、资源管理等模块

授权

除开源版本外,本商城还提供商业版本的商城,欲知详情,请访问官网。

商城官网:https://www.mall4j.com

商城使用 AGPLv3 开源,请遵守 AGPLv3 的相关条款,或者联系作者获取商业授权(https://www.mall4j.com)

项目链接

JAVA后台:https://gitee.com/gz-yami/mall4cloud

平台端:https://gitee.com/gz-yami/mall4cloud-platform

商家端:https://gitee.com/gz-yami/mall4cloud-multishop

uni-app:https://gitee.com/gz-yami/mall4cloud-uniapp

部署教程

1.安装nodejs

NodeJS 项目要求最低 18.12.0,推荐 20.9.0

如果不了解怎么安装nodejs的,可以参考 菜鸟教程的nodejs相关

2.启动

  • 项目要求使用 pnpm 包管理工具
  • 使用编辑器打开项目,在根目录执行以下命令安装依赖
text
pnpm install
  • 运行
text
pnpm run dev
  • 部署
text
pnpm run build
  • 如果不想使用 pnpm,请删除 package.json 文件中 preinstall 脚本后再进行安装
json
{
    "scripts" : {
        "preinstall": "npx only-allow pnpm"  // 使用其他包管理工具(npm、yarn、cnpm等)请删除此命令
    }
}

目录结构

text
├── build                      # 构建相关
├── public                     # 静态资源
│   │── favicon.ico            # favicon图标
│   └── index.html             # html模板
├── src                        # 源代码
│   ├── api                    # 所有请求(根据不同后台不同的服务分包)
│   ├── assets                 # 主题 字体等静态资源
│   ├── components             # 全局公用组件
│   ├── directive              # 全局指令
│   ├── filters                # 全局 filter
│   ├── icons                  # 项目所有 svg icons
│   ├── lang                   # 国际化 language
│   ├── layout                 # 全局 layout
│   ├── router                 # 路由
│   ├── store                  # 全局 store管理
│   ├── styles                 # 全局样式
│   ├── utils                  # 全局公用方法
│   ├── views                  # views 所有页面
│   ├── App.vue                # 入口页面
│   ├── main.js                # 入口文件 加载组件 初始化等
│   └── permission.js          # 权限管理
├── tests                      # 测试
├── .env.xxx                   # 环境变量配置
├── .eslintrc.js               # eslint 配置项
├── .babelrc                   # babel-loader 配置
├── .travis.yml                # 自动化CI配置
├── vue.config.js              # vue-cli 配置
├── postcss.config.js          # postcss 配置
└── package.json               # package.json

运行相关截图

后台截图

提交反馈

  • Mall4j官网 https://www.mall4j.com

  • 如需购买商业版源码,请联系商务微信

  • mall4cloud开源技术QQ群:561496886

springboot版本商城请点击

https://gitee.com/gz-yami/mall4j

更多内容请查看 主项目 https://gitee.com/gz-yami/mall4cloud


Overview (`front-end/mall4cloud-platform/README.md`)

README

前言

本商城是基于Spring Cloud、Nacos、Seata、Mysql、Redis、RocketMQ、canal、ElasticSearch、minio的微服务B2B2C电商商城系统,采用主流的互联网技术架构、全新的UI设计、支持集群部署、服务注册和发现以及拥有完整的订单流程等,代码完全开源,没有任何二次封装,是一个非常适合二次开发的电商平台系统。

本商城致力于为中大型企业打造一个功能完整、易于维护的微服务B2B2C电商商城系统,采用主流微服务技术实现。后台管理系统包含平台管理,店铺管理、商品管理、订单管理、规格管理、权限管理、资源管理等模块

授权

除开源版本外,本商城还提供商业版本的商城,欲知详情,请访问官网。

商城官网:https://www.mall4j.com

商城使用 AGPLv3 开源,请遵守 AGPLv3 的相关条款,或者联系作者获取商业授权(https://www.mall4j.com)

项目链接

JAVA后台:https://gitee.com/gz-yami/mall4cloud

平台端:https://gitee.com/gz-yami/mall4cloud-platform

商家端:https://gitee.com/gz-yami/mall4cloud-multishop

uni-app:https://gitee.com/gz-yami/mall4cloud-uniapp

部署教程

1.安装nodejs

NodeJS 项目要求最低 18.12.0,推荐 20.9.0

如果不了解怎么安装nodejs的,可以参考 菜鸟教程的nodejs相关

2.启动

  • 项目要求使用 pnpm 包管理工具
  • 使用编辑器打开项目,在根目录执行以下命令安装依赖
text
pnpm install
  • 运行
text
pnpm run dev
  • 部署
text
pnpm run build
  • 如果不想使用 pnpm,请删除 package.json 文件中 preinstall 脚本后再进行安装
json
{
    "scripts" : {
        "preinstall": "npx only-allow pnpm"  // 使用其他包管理工具(npm、yarn、cnpm等)请删除此命令
    }
}

目录结构

text
├── build                      # 构建相关
├── public                     # 静态资源
│   │── favicon.ico            # favicon图标
│   └── index.html             # html模板
├── src                        # 源代码
│   ├── api                    # 所有请求(根据不同后台不同的服务分包)
│   ├── assets                 # 主题 字体等静态资源
│   ├── components             # 全局公用组件
│   ├── directive              # 全局指令
│   ├── filters                # 全局 filter
│   ├── icons                  # 项目所有 svg icons
│   ├── lang                   # 国际化 language
│   ├── layout                 # 全局 layout
│   ├── router                 # 路由
│   ├── store                  # 全局 store管理
│   ├── styles                 # 全局样式
│   ├── utils                  # 全局公用方法
│   ├── views                  # views 所有页面
│   ├── App.vue                # 入口页面
│   ├── main.js                # 入口文件 加载组件 初始化等
│   └── permission.js          # 权限管理
├── tests                      # 测试
├── .env.xxx                   # 环境变量配置
├── .eslintrc.js               # eslint 配置项
├── .babelrc                   # babel-loader 配置
├── .travis.yml                # 自动化CI配置
├── vue.config.js              # vue-cli 配置
├── postcss.config.js          # postcss 配置
└── package.json               # package.json

运行相关截图

后台截图

提交反馈

  • Mall4j官网 https://www.mall4j.com

  • 如需购买商业版源码,请联系商务微信

  • mall4cloud开源技术QQ群:561496886

springboot版本商城请点击

https://gitee.com/gz-yami/mall4j

更多内容请查看 主项目 https://gitee.com/gz-yami/mall4cloud


Overview (`front-end/mall4cloud-uniapp/README.md`)

  • README

    前言

    本商城是基于Spring Cloud、Nacos、Seata、Mysql、Redis、RocketMQ、canal、ElasticSearch、minio的微服务B2B2C电商商城系统,采用主流的互联网技术架构、全新的UI设计、支持集群部署、服务注册和发现以及拥有完整的订单流程等,代码完全开源,没有任何二次封装,是一个非常适合二次开发的电商平台系统。

    本商城致力于为中大型企业打造一个功能完整、易于维护的微服务B2B2C电商商城系统,采用主流微服务技术实现。后台管理系统包含平台管理,店铺管理、商品管理、订单管理、规格管理、权限管理、资源管理等模块

    授权

    除开源版本外,本商城还提供商业版本的商城,欲知详情,请访问官网。

    商城官网:https://www.mall4j.com

    商城使用 AGPLv3 开源,请遵守 AGPLv3 的相关条款,或者联系作者获取商业授权(https://www.mall4j.com)

    项目链接

    JAVA后台:https://gitee.com/gz-yami/mall4cloud

    平台端:https://gitee.com/gz-yami/mall4cloud-platform

    商家端:https://gitee.com/gz-yami/mall4cloud-multishop

    uni-app:https://gitee.com/gz-yami/mall4cloud-uniapp

    部署教程

    1.安装nodejs

    NodeJS 项目要求最低 18.12.0,推荐 20.9.0

    如果不了解怎么安装nodejs的,可以参考 菜鸟教程的nodejs相关

    2.启动

    • 项目要求使用 pnpm 包管理工具
    • 使用编辑器打开项目,在根目录执行以下命令安装依赖
    text
    pnpm install
    • 运行
    text
    pnpm run dev:h5
    • 部署
    text
    pnpm run build:h5
    • 如果不想使用 pnpm,请删除 package.json 文件中 preinstall 脚本后再进行安装
    json
    {
        "scripts" : {
            "preinstall": "npx only-allow pnpm"  // 使用其他包管理工具(npm、yarn、cnpm等)请删除此命令
        }
    }

    技术介绍

    本项目是一个uniapp的项目,使用cli进行构建,目录结构如下

    text
    ├── dist                       # 构建相关
    ├── src                        # 源代码
    │   ├── components             # 全局公用组件
    │   ├── hybrid                 # webview本地页面
    │   ├── js_sdk                 # 外部js
    │   ├── lang                   # 国际化 language
    │   ├── package-activities     # 活动分包
    │   ├── package-refund         # 退款分包
    │   ├── package-shop           # 店铺分包
    │   ├── package-user           # 用户分包
    │   ├── pages                  # 主包
    │   ├── router                 # 路由配置
    │   ├── static                 # 静态资源
    │   ├── uni_modules            # uni第三方组件
    │   ├── utils                  # 全局公用方法
    │   ├── wxs                    # wxs
    │   ├── app.css                # 全局样式
    │   ├── App.vue                # 入口页面
    │   ├── main.js                # 入口文件 加载组件 初始化等
    │   ├── manifest.json          # uniapp 项目配置
    │   ├── pages.json             # 页面配置文件
    │   ├── manifest.json          # uniapp 项目配置
    │   ├── popup.scss             # 全局弹窗样式
    │   └── uni.scss                # uni样式变量
    ├── .editorconfig              # 编辑器配置
    ├── .env.xxx                   # 环境变量配置
    ├── .eslintxxx.xx              # eslint 相关配置
    ├── .gitignore                 # git 忽略清单
    ├── .npmrc                        # npm 配置
    ├── Dockerfile                 # docker部署配置
    ├── index.html                    # html 模板
    ├── nginx.conf                 # nginx 配置
    ├── package.json               # package.json
    ├── tsconfig.json               # ts 编译配置
    └── vite.config.js             # vite 配置文件

    运行相关截图

    1.小程序截图

    2.uni-app截图

    提交反馈

    • Mall4j官网 https://www.mall4j.com

    • 如需购买商业版源码,请联系商务微信

    • mall4cloud开源技术QQ群:561496886

    springboot版本商城请点击

    https://gitee.com/gz-yami/mall4j

    更多信息请查看官网


Overview (`mall4cloud-common/mall4cloud-common-cache/README.md`)

一些通用的缓存配置

缓存key命名规范:

服务名:业务名:方法名:key, 大小写以下划线分割 如
mall4cloud_oauth:token:access:
mall4cloud_oauth:token:refresh_to_access:
mall4cloud_oauth:token:uid_to_access:


Overview (`doc/8-部署运维/2-中间件-docker-compose/README.md`)

中间件 Docker Compose

这个目录保留 Mall4cloud 本地或单机服务器启动中间件所需的 compose 文件和配置材料。它不是通用 Docker 教程;Docker/Compose 安装问题请先查官方文档。

先改服务器地址

compose 和初始化 SQL 中仍保留示例地址。启动前请把本目录下的示例 IP 统一替换为你的服务器或本机局域网 IP:

bash
192.168.1.46 -> <你的服务器IP>

需要重点核对的地方:

  • docker-compose.yaml、docker-compose-native.yaml 中的 Nacos、MinIO、Seata、RocketMQ 地址。
  • mysql/initdb/mall4cloud_nacos.sql 中 Nacos 配置中心写入的 Redis、Seata、OSS、RocketMQ、各服务 MySQL 地址。
  • seata/application.yml 中的 Seata 数据库地址。
  • canal/conf/example/instance.properties 中的 MySQL 地址和账号。

启动前权限

Linux 服务器上进入本目录后执行:

bash
chmod -R 777 ./rocketmq
chmod -R 666 ./minio/data
chmod -R 777 ./elasticsearch/data

启动命令

优先使用带国内镜像地址的 compose:

bash
docker compose -f docker-compose.yaml up -d --build

如果服务器访问 Docker Hub 稳定,也可以使用原生镜像版本:

bash
docker compose -f docker-compose-native.yaml up -d --build

docker-compose.yaml 使用处理过的镜像地址,适合国内网络优先尝试。docker-compose-native.yaml 使用原生镜像名,只有在服务器 Docker Hub 或镜像源稳定时再使用;不需要重命名文件,直接用 -f 指定即可。

首次拉取镜像体积较大,等待时间较长是正常现象。若 RocketMQ 报 No route info of this topic,先检查 rocketmq/broker/conf/broker.conf 是否成功挂载、rocketmq/ 目录权限是否足够,再重建 broker/dashboard/namesrv。

端口与默认账号

中间件 端口/地址 默认账号
MySQL <你的服务器IP>:3306 root / 80jpnH4.r5g
Redis <你的服务器IP>:6379 密码 80jpnH4.r5g
Nacos 控制台 http://<你的服务器IP>:8080/index.html 本目录初始化 SQL 写入的是 nacos / 80jpnH4.r5g,服务配置也必须保持一致
MinIO API http://<你的服务器IP>:9000 用于后端和前端资源访问
MinIO 控制台 http://<你的服务器IP>:9001 admin / 80jpnH4.r5g
Elasticsearch http://<你的服务器IP>:9200 elastic / 80jpnH4.r5g
RocketMQ namesrv <你的服务器IP>:9876 无控制台账号
RocketMQ dashboard http://<你的服务器IP>:8180 当前未配置登录保护,生产环境不要裸露
Canal <你的服务器IP>:11111 由 canal/conf 配置
Seata <你的服务器IP>:8091 Seata 2.6 只使用 8091

MinIO 桶

进入 MinIO 控制台后创建桶:

text
mall4cloud

端口用途:

  • 9000:对象访问和上传地址,Nacos 的 biz.oss.endpoint、前端 VITE_APP_RESOURCES_URL 都应指向这里。
  • 9001:控制台地址,只给运维人员使用。

如果前端图片无法展示,先检查桶是否存在、桶策略是否允许读取、Nacos 中 biz.oss.resources-url 是否是 http://<你的服务器IP>:9000/mall4cloud。

参考截图:

Elasticsearch 索引

搜索服务依赖 product 和 order 两类索引。mapping 以仓库根目录为准:

创建索引时用 Elasticsearch 账号 elastic / 80jpnH4.r5g。下面截图只作为操作界面参考:

Nacos、Canal、Seata

初始化配置在 mysql/initdb 下:

  • mall4cloud_nacos.sql:写入 Nacos 配置中心,包含网关路由、数据源、Redis、OSS、RocketMQ、Seata 地址。
  • mall4cloud_seata.sql:Seata 事务表。
  • Canal 相关配置保留在 canal/conf。

Nacos v3 控制台走 8080,服务客户端配置仍使用 8848,Nacos 2/3 客户端还会用到 9848、9849。防火墙或安全组只放开控制台端口时,Java 服务仍可能连不上。

Seata 2.6 本目录的 compose 只暴露 8091。如果需要控制台能力,请按 Seata 官方方式单独部署,不要在 seata/application.yml 中添加未验证的 console 配置。

验收

  • docker ps 能看到 MySQL、Redis、Nacos、Seata、ES、Canal、RocketMQ、MinIO 容器运行。
  • Nacos 控制台能登录,并能看到 application.yml、mall4cloud-gateway.yml 等配置。
  • MySQL 中存在 mall4cloud_auth、mall4cloud_rbac、mall4cloud_product、mall4cloud_order 等库。
  • MinIO 存在 mall4cloud 桶。
  • RocketMQ dashboard 能看到 namesrv。

如果这些都通过,再回到 环境搭建/后端启动。


Overview (`front-end/mall4cloud-multishop/public/static/js/tinymce/js/tinymce/langs/README.md`)

This is where language files should be placed.

Please DO NOT translate these directly use this service: https://www.transifex.com/projects/p/tinymce/


Doc 1 项目概览 1 项目定位与阅读路径 (`doc/1-项目概览/1-项目定位与阅读路径.md`)

项目定位与阅读路径

Mall4cloud 开源版是一个微服务 B2B2C 商城系统。当前仓库包含后端微服务、数据库脚本、中间件配置和三个前端工程:平台端、商家端、uni-app 用户端。

适合谁读

读者 先解决的问题
新维护者 先把项目跑起来,再知道服务、数据库和前端怎么连起来。
二次开发者 先理解权限、数据表和后台管理功能模式,再新增后台功能。
开源评估者 先判断技术栈、运行成本、授权边界和是否符合自己的商城场景。

30 分钟目标:跑起基础链路

先不用跑全量业务,重点确认网关、登录、权限和一个后台端可用:

  1. MySQL、Redis、Nacos、MinIO 先可用。
  2. 网关 mall4cloud-gateway 在 8000 端口可访问。
  3. 认证、权限、平台端或商家端相关服务启动。
  4. 管理后台能打开登录页,并能请求网关。

如果使用 Docker Compose 中间件,先看 中间件 Docker Compose。

2 小时目标:读懂结构

按这个顺序建立地图:

  1. 模块职责地图
  2. 后端分层与模块
  3. 前端工程与动态路由
  4. 登录认证与权限链路
  5. 数据库阅读路线

读完后应该能回答:请求从前端发出后,经过网关到哪个服务;菜单从哪里来;按钮权限为什么能隐藏;商品和订单核心表怎么关联。

1 天目标:完成一次后台二开

优先做后台管理功能,不先碰订单、支付、库存、结算。可以从热搜、轮播图、附件分组这类后台 CRUD 学起,再迁移到自己的功能。

学习路线:

  1. 读 核心表速查。
  2. 读 权限链路。
  3. 照 后台管理功能二开示例 写自己的文档或代码。
  4. 用 命名约定与验收清单 自检。

阅读原则

  • 每个目录对应一个学习阶段。
  • 检查题都给答案和原因。
  • 结论以当前源码、配置和 SQL 为准。

Doc 1 项目概览 2 模块职责地图 (`doc/1-项目概览/2-模块职责地图.md`)

模块职责地图

本页帮助你先知道“改哪里”,再去看细节。

后端服务

模块 职责 常见二开入口
mall4cloud-gateway 网关,端口 8000,按 Nacos 路由把 /mall4cloud_xxx/** 转给服务 调整跨域、路由、统一入口
mall4cloud-auth 登录、Token 发放和校验 登录方式、账号体系
mall4cloud-rbac 菜单、角色、按钮权限、接口权限 新增菜单和按钮权限
mall4cloud-platform 平台端后台业务 平台用户、系统配置、平台运营功能
mall4cloud-multishop 商家端后台业务 店铺用户、店铺装修、商家运营功能
mall4cloud-product 商品、分类、品牌、SKU、库存 商品管理和库存相关功能
mall4cloud-order 订单、订单项、收货地址、发货 订单查询和发货,先阅读再改造
mall4cloud-payment 支付信息和支付通知 支付接入,先阅读再改造
mall4cloud-biz 文件上传、附件等通用业务 MinIO 上传、附件管理
mall4cloud-search Elasticsearch 搜索、Canal 消息消费 商品/订单索引同步
mall4cloud-user 用户、地址、区域 用户资料和收货地址
mall4cloud-leaf 分布式 ID 新表主键生成策略
mall4cloud-api 服务间 Feign 接口 跨服务调用契约
mall4cloud-common 公共响应、异常、分页、安全、缓存、数据库、消息 新功能复用基础能力

前端工程

工程 角色 怎么读
front-end/mall4cloud-platform 平台端管理后台 重点读登录、动态菜单、后台列表页模式
front-end/mall4cloud-multishop 商家端管理后台 重点读商家端菜单和同类 CRUD 页面
front-end/mall4cloud-uniapp 用户端 先核对接口地址,后台跑通后再看页面

平台端和商家端都是 Vue 3 + Vite + Pinia + Element Plus,环境变量使用 VITE_APP_*。

数据库脚本

目录/文件 用途
db/*.sql 当前库表结构和初始数据,是数据模型文档的主要依据
doc/8-部署运维/2-中间件-docker-compose/mysql/initdb/*.sql Docker Compose 启动中间件时导入 Nacos、Seata 等配置
es/product.md、es/order.md Elasticsearch 索引 mapping

请求链路

管理后台请求 VITE_APP_BASE_API,默认指向网关 8000。网关读取 Nacos 中的路由配置,例如 /mall4cloud_rbac/** 转到 mall4cloud-rbac。业务服务再通过 MySQL、Redis、RocketMQ、Seata、MinIO、Elasticsearch 等中间件完成各自职责。

练习:我应该改哪个模块

问题:要新增一个“公告管理”后台功能,第一步应该去订单服务吗?

答案:不应该。公告管理更像平台端运营能力。优先在 mall4cloud-platform 增加后端接口,在 front-end/mall4cloud-platform 增加页面,在 mall4cloud-rbac 的菜单和按钮权限中补权限。

为什么:订单服务涉及交易状态和库存协作,不适合作为学习项目分层的第一个改动点。


Doc 1 项目概览 3 学习与自检 (`doc/1-项目概览/3-学习与自检.md`)

学习与自检

这部分说明怎么读文档、怎么确认自己读懂了。检查题不是考试,答案和原因都会直接给出。

阅读时先看三件事

问题 读到什么程度算够
我现在要做什么? 知道本页目标和下一步入口。
项目怎么实现? 能指出对应源码、配置或 SQL。
我怎么知道自己做对了? 能对照验收信号或检查题说明原因。

检查题怎么用

每道题都有三个部分:

  1. 题目:先自己判断一次。
  2. 答案:直接给出正确结论。
  3. 为什么:说明依据来自哪个代码、配置或 SQL 事实。

示例:

问题:平台端前端应该配置 VUE_APP_BASE_API 还是 VITE_APP_BASE_API?

答案:配置 VITE_APP_BASE_API。

为什么:当前平台端和商家端是 Vite 工程,.env.development 中使用 VITE_APP_BASE_API,代码通过 import.meta.env 读取。

读者自检

阶段 自检答案应该是什么
启动后 网关 8000 可访问,后台登录页能请求到网关。
读完框架后 能说出 Controller -> Service -> Mapper -> DB 的基本链路和 Feign 的用途。
读完权限后 能说出菜单控制页面可见性,按钮权限控制按钮显示,后端接口权限控制请求是否放行。
读完数据模型后 能说出 menu、menu_permission、role_menu、user_role 的关系。

避免误判

  • 不用截图代替源码、配置或 SQL 结论。
  • 不把通用安装教程当成项目配置。
  • 不把未经核对的命令写成当前可用。

Doc 2 环境搭建 1 环境要求 (`doc/2-环境搭建/1-环境要求.md`)

环境要求

以下版本来自当前仓库配置。后台前端是 Vue 3 + Vite,后端要求 JDK 17。

后端

组件 当前要求 依据
JDK 17 根 pom.xml 的 java.version
Maven 3.9+ 当前多模块 Maven 工程
Spring Boot 4.0.3 根 pom.xml
Spring Cloud 2025.1.1 根 pom.xml
Spring Cloud Alibaba 2025.1.0.0 根 pom.xml
Nacos Client 3.1.1 根 pom.xml
Seata 2.6.0 根 pom.xml

前端

组件 当前要求 依据
Node.js `^20.19.0
pnpm >=8 <11 平台端/商家端 package.json
Vite 8.x 平台端/商家端 package.json
Vue 3.5.x 平台端/商家端 package.json

前端包管理器必须使用 pnpm。package.json 里有 preinstall: npx only-allow pnpm,用 npm/yarn 安装会被拦截。

中间件

组件 版本 当前配置来源
MySQL 8.0.x Docker Compose 使用 MySQL 8
Redis 7.0 Docker Compose
Nacos 3.1.1 Docker Compose
Seata 2.6.0 Docker Compose
RocketMQ 5.2.0 Docker Compose
Elasticsearch 7.17.21 Docker Compose
MinIO RELEASE.2024-04-18T19-09-19Z Docker Compose
Canal 1.1.7 Docker Compose

检查题

问题:当前后台前端启动前,应该先安装 pnpm 还是直接用 npm install?

答案:先安装并使用 pnpm。

为什么:平台端和商家端 package.json 声明了 pnpm 版本范围,并用 only-allow pnpm 限制安装工具。

问题:当前后端是否还是 JDK 8 项目?

答案:不是,当前要求是 JDK 17。

为什么:根 pom.xml 的 java.version 是 17。


Doc 2 环境搭建 2 数据库初始化 (`doc/2-环境搭建/2-数据库初始化.md`)

数据库初始化

数据库初始化分两类:业务库脚本和中间件初始化脚本。

业务库脚本

仓库根目录 db/ 下是当前业务表结构和初始数据:

文件 数据库
mall4cloud_auth.sql 账号与登录
mall4cloud_rbac.sql 菜单、角色、按钮权限
mall4cloud_platform.sql 平台端用户与配置
mall4cloud_multishop.sql 店铺、商家用户、热搜、轮播
mall4cloud_product.sql 商品、SKU、库存
mall4cloud_order.sql 订单、订单项、收货地址
mall4cloud_biz.sql 附件和附件分组
mall4cloud_user.sql、mall4cloud_user_area_data.sql 用户与地区数据
mall4cloud_leaf.sql 分布式 ID
mall4cloud_payment.sql 支付信息

如果不用 Docker Compose 自动初始化,请手动创建库并执行这些 SQL。

中间件初始化脚本

使用 中间件 Docker Compose 时,mysql/initdb 会导入 Nacos、Seata、Canal 等配置。这里包含网关路由、各服务数据源、Redis、RocketMQ、OSS、Seata 地址。

启动前请先把示例 IP 替换为你的环境 IP,否则服务可能注册到了错误地址。

默认账号

当前初始化数据里可见:

端 用户名 密码 说明
平台端 admin 123456 根 README 对应平台端仓库说明;账号记录在 mall4cloud_auth.sql、mall4cloud_platform.sql
商家端 admin 123456 根 README 对应商家端仓库说明;账号记录在 mall4cloud_auth.sql、mall4cloud_multishop.sql

如果登录失败,先确认导入的 auth、platform、multishop、rbac 库来自同一套脚本,不要混用其他版本数据。

验收

  • MySQL 中存在 mall4cloud_auth、mall4cloud_rbac、mall4cloud_product、mall4cloud_order 等库。
  • mall4cloud_auth.auth_account 中有平台端和商家端账号。
  • mall4cloud_rbac.menu 和 mall4cloud_rbac.menu_permission 中有菜单和按钮权限数据。
  • Nacos 中有 application.yml 和 mall4cloud-gateway.yml。

检查题

问题:为什么只导入 db/mall4cloud_product.sql 不能完成后台登录?

答案:登录至少还依赖 mall4cloud_auth、mall4cloud_rbac,平台端或商家端还依赖对应的 mall4cloud_platform 或 mall4cloud_multishop。

为什么:账号在 auth 库,菜单和权限在 rbac 库,登录后用户信息来自平台端或商家端业务库。


Doc 2 环境搭建 3 后端启动 (`doc/2-环境搭建/3-后端启动.md`)

后端启动

先跑“登录 + 权限 + 一个后台端”链路,不要一开始全量启动所有业务。

先启动中间件

至少需要:

  • MySQL
  • Redis
  • Nacos
  • MinIO

如果要验证商品搜索、订单搜索或商品发布后的索引同步,再启动 Elasticsearch、RocketMQ、Canal。

服务端口

服务 端口
mall4cloud-gateway 8000
mall4cloud-leaf 9100
mall4cloud-auth 9101
mall4cloud-rbac 9102
mall4cloud-multishop 9103
mall4cloud-product 9104
mall4cloud-user 9105
mall4cloud-order 9106
mall4cloud-search 9108
mall4cloud-platform 9112
mall4cloud-payment 9113
mall4cloud-biz 9000

这些端口来自各服务 bootstrap.yml 和网关 application.yml。

最小平台端链路

启动:

  1. mall4cloud-gateway
  2. mall4cloud-auth
  3. mall4cloud-rbac
  4. mall4cloud-platform
  5. mall4cloud-biz

如果页面需要商品、店铺或订单数据,再启动对应服务。

最小商家端链路

启动:

  1. mall4cloud-gateway
  2. mall4cloud-auth
  3. mall4cloud-rbac
  4. mall4cloud-multishop
  5. mall4cloud-biz

商品管理页面还会需要 mall4cloud-product。

Nacos 地址

各服务默认从环境变量读取 Nacos:

text
NACOS_HOST,默认 192.168.1.46
NACOS_PORT,默认 8848

本地开发时,如果 Nacos 不在 192.168.1.46,请设置环境变量或修改启动配置。还要注意:当前服务 bootstrap 中 Nacos 用户名/密码默认写的是 nacos/nacos;如果使用本仓库 Compose 初始化 SQL,Nacos 用户表写入的是 nacos / 80jpnH4.r5g,两边必须统一。

开发机资源

一次在 IDEA 中启动多个微服务会比较吃内存。当前项目使用 JDK 17,如果本机内存紧张,优先只启动最小链路服务,并给单个服务配置类似 -Xms512m -Xmx512m -Xss256k 的启动参数。

不要无脑全仓替换 192.168.1.46。更稳妥的做法是重点核对 bootstrap、Nacos 配置、Compose、Canal、Seata、RocketMQ 和前端 .env.* 中的示例地址。

验收

  • 网关日志显示服务启动在 8000。
  • 服务能注册到 Nacos。
  • 访问 http://<网关IP>:8000/mall4cloud_rbac/menu/route 时,如果未登录返回未授权,说明路由到了后端。
  • 登录成功后,前端能获取菜单。

检查题

问题:前端请求应该直连 mall4cloud-rbac:9102 吗?

答案:不应该,管理后台应请求网关 8000。

为什么:Nacos 中 mall4cloud-gateway.yml 配置了 /mall4cloud_rbac/** 等路由,前端只需要配置网关地址。


Doc 2 环境搭建 4 管理后台启动 (`doc/2-环境搭建/4-管理后台启动.md`)

管理后台启动

平台端和商家端都是 Vite 工程,命令和环境变量以当前 package.json、.env.* 为准。

安装依赖

平台端:

bash
cd front-end/mall4cloud-platform
pnpm install
pnpm dev

商家端:

bash
cd front-end/mall4cloud-multishop
pnpm install
pnpm dev

当前 Vite dev server 端口是 9527。如果两个后台同时启动,第二个需要手动换端口或按 Vite 提示处理。

关键环境变量

.env.development 和 .env.production 使用:

text
VITE_APP_BASE_API
VITE_APP_RESOURCES_URL
VITE_APP_RESOURCES_TYPE

本地常见配置:

text
VITE_APP_BASE_API = 'http://<网关IP>:8000'
VITE_APP_RESOURCES_URL = 'http://<MinIO-IP>:9000/mall4cloud'
VITE_APP_RESOURCES_TYPE = '1'

不要使用 VUE_APP_*,当前后台只读取 VITE_APP_*。

登录

默认账号参考 数据库初始化:

  • 平台端:admin / 123456
  • 商家端:admin / 123456

登录失败先看浏览器 Network:

  • 请求是否发到 VITE_APP_BASE_API。
  • 是否返回 A00004 未授权。
  • 是否跨域失败。
  • auth、rbac、platform/multishop 服务是否已启动。

检查题

问题:图片能上传但前端显示 404,先改哪个配置?

答案:先核对 VITE_APP_RESOURCES_URL 和 Nacos 中 biz.oss.resources-url 是否都指向 http://<MinIO-IP>:9000/mall4cloud。

为什么:上传和展示使用的资源域名必须和 MinIO 桶地址一致,后台返回的是对象路径,前端需要拼接正确资源地址。


Doc 2 环境搭建 5 移动端接口地址 (`doc/2-环境搭建/5-移动端接口地址.md`)

移动端接口地址

本页只说明 uni-app 用户端如何接后端,不展开移动端源码结构。

当前范围

front-end/mall4cloud-uniapp 是用户端工程。新维护者先确保后端网关和管理后台可用,再处理移动端。

要核对什么

  1. 网关地址:应指向 http://<网关IP>:8000。
  2. 图片资源地址:应指向 http://<MinIO-IP>:9000/mall4cloud。
  3. H5、小程序、App 构建模式下的接口地址是否分别配置。

为什么不先看移动端源码

先跑通网关、登录、权限和管理后台,再处理移动端。移动端涉及发布平台、运行时权限、端侧兼容和页面业务,不适合作为第一批启动任务。

检查题

问题:后台管理端没跑通时,是否应该先调 uni-app 页面?

答案:不要。

为什么:后台登录、权限、网关、数据库、中间件是基础链路。基础链路没通时,移动端错误会混入更多端侧变量,排查成本更高。


Doc 3 技术框架 1 后端分层与模块 (`doc/3-技术框架/1-后端分层与模块.md`)

后端分层与模块

Mall4cloud 后端是多模块 Maven 工程。二开时优先沿用现有分层,不要为了一个功能引入新架构。

常见分层

层 常见目录 职责
Controller controller 接收 HTTP 请求、做参数校验、调用 Service、返回 ServerResponseEntity
DTO dto 前端传入参数
VO vo 返回给前端的数据
Service service、service/impl 业务编排、事务边界、跨服务调用
Mapper mapper MyBatis 数据访问接口
XML resources/mapper SQL
Model model 与数据库表结构对应
FeignClient mall4cloud-api-* 服务间调用契约
Common mall4cloud-common-* 公共响应、异常、分页、缓存、安全、消息等能力

一个后台列表请求怎么走

以常见列表页为例:

  1. 前端页面调用 src/api/** 中的方法。
  2. 请求进入网关 mall4cloud-gateway:8000。
  3. 网关按 Nacos 路由转发到对应服务。
  4. Controller 接收 PageDTO 和搜索条件。
  5. Service 调 Mapper 查询。
  6. PageUtil.doPage 生成 PageVO。
  7. Controller 返回 ServerResponseEntity.success(pageVO)。

Feign 的位置

跨服务调用不要直接拼 URL。项目把内部接口放在 mall4cloud-api 下,例如商品库存锁定、用户信息、权限校验等。服务实现方实现对应 Feign 接口,调用方只依赖 API 模块。

新功能落点

  • 后台 CRUD 功能优先找同业务域已有的 HotSearch、IndexImg、Attr、Category 模式。
  • 需要跨服务时,先判断是否已有 mall4cloud-api-* 接口;没有再补接口契约。
  • 需要事务跨服务时,参考已有 @GlobalTransactional 用法,不要只加本地事务。

检查题

问题:新增后台表单时,前端传来的对象应该直接用 Model 接收吗?

答案:不要,优先使用 DTO。

为什么:当前项目用 DTO 承接前端输入,用 Model 对应数据库表,用 VO 返回前端。直接暴露 Model 容易把数据库字段和接口契约绑死。


Doc 3 技术框架 2 前端工程与动态路由 (`doc/3-技术框架/2-前端工程与动态路由.md`)

前端工程与动态路由

平台端和商家端是 Vue 3 + Vite + Pinia + Element Plus,环境变量使用 VITE_APP_*。

关键目录

目录 用途
src/api 后端接口封装
src/views/modules 后台业务页面
src/router 基础静态路由
src/stores/modules/user.js 登录用户、权限列表、菜单 ID
src/stores/modules/permission.js 动态路由生成
src/directive/permission v-permission 按钮权限
src/directive/rich 富文本展示前的 DOMPurify 清洗
.env.* VITE_APP_* 环境变量

动态菜单怎么来

登录后,src/permission.js 执行:

  1. getUserInfo() 获取用户信息和是否管理员。
  2. listPermissions() 获取按钮权限编码。
  3. 非管理员调用 listMenuIds() 获取可见菜单 ID。
  4. permissionStore.generateRoutes(menuIds) 调 /mall4cloud_rbac/menu/route 获取菜单路由。
  5. component 为 Layout 时加载布局,否则从 src/views/modules 下按路径加载页面。

后台菜单的 component 字段必须和页面路径对应。例如 product/category 会加载 src/views/modules/product/category/index.vue。

按钮权限怎么来

页面按钮使用:

vue
v-permission="['product:category:save']"

用户登录后,前端把 /mall4cloud_rbac/menu_permission/list 返回的权限编码放到 roles。v-permission 指令判断当前用户是否有对应编码,没有就移除按钮。管理员直接放行。

检查题

问题:新增菜单后,页面文件存在但点击菜单空白,最可能先查什么?

答案:先查 menu.component 是否能映射到 src/views/modules/<component>/index.vue 或 src/views/modules/<component>.vue。

为什么:动态路由通过 import.meta.glob('../../views/modules/**/**.vue') 加载页面,路径对不上就没有组件。


Doc 4 技术实现 1 登录认证与权限链路 (`doc/4-技术实现/1-登录认证与权限链路.md`)

登录认证与权限链路

权限链路分三层:登录 Token、菜单可见性、按钮/接口权限。二开后台功能时三层都要考虑。

登录 Token

  1. 前端登录调用 auth 服务。
  2. mall4cloud-auth 校验账号密码后,通过 TokenStore.storeAndGetVo 生成 access token 和 refresh token,并把用户信息写入 Redis。
  3. 前端后续请求在 Authorization 请求头带 token。
  4. 业务服务里的 AuthFilter 调 TokenFeignClient.checkToken(accessToken) 校验 token。
  5. 校验成功后,用户信息放入 AuthUserContext。

Token 相关的当前入口:

入口 作用
LoginController /ua/login 登录后清理权限缓存,并返回 token
TokenStore 保存、刷新、删除、解析 token
TokenFeignController 提供内部 checkToken 校验
AuthFilter 每个业务请求进入服务后的 token 和权限校验

不需要登录的路径由 AuthConfigAdapter.excludePathPatterns 控制。默认放行:

  • /v3/api-docs
  • 内部 Feign 路径
  • /**/ua/**

菜单权限

菜单数据在 mall4cloud_rbac.menu。关键字段:

字段 用途
menu_id 菜单 ID
parent_id 父菜单
biz_type 1 商家端,2 平台端
path 前端路由路径
component 前端页面组件路径
title、icon 侧边栏展示

非管理员登录后,前端用 /mall4cloud_rbac/menu/list_menu_ids 获取可见菜单 ID,再过滤 /mall4cloud_rbac/menu/route 返回的菜单。

按钮权限

按钮权限数据在 mall4cloud_rbac.menu_permission。关键字段:

字段 用途
menu_id 归属菜单
permission 前端按钮权限编码
uri 后端接口 URI
method 请求方法:1 GET、2 POST、3 PUT、4 DELETE
biz_type 商家端或平台端

角色授权通过 role_menu 关联菜单和按钮权限,用户通过 user_role 关联角色。

后端接口权限

AuthFilter 对平台端和商家端用户会调用 PermissionFeignClient.checkPermission。当前 AuthConfigAdapter 没有全局 needRbac() 开关;是否进入 RBAC 校验由用户 sysType 决定,平台端和商家端会校验,普通用户端直接放行 RBAC。

mall4cloud-rbac 中的实现会:

  1. 查询用户拥有的权限编码。
  2. 查询当前端所有 uri + method -> permission 映射。
  3. 用 AntPathMatcher 匹配请求 URI 和方法。
  4. 如果接口匹配到权限要求,用户必须拥有该权限;如果没有匹配到权限要求,则放行。

这意味着:只加前端按钮权限不够,后端接口权限也要能对应上。

新增页面/按钮时要做什么

要新增 必做
页面菜单 新增 menu,component 对应前端页面路径
新增按钮 新增 menu_permission,编码与前端 v-permission 一致
接口保护 menu_permission.uri 和 method 对上 Controller 路径和 HTTP 方法
给角色授权 在角色管理中勾选菜单和按钮权限

排错清单

现象 答案
菜单不显示 用户不是管理员时,先查角色是否勾选该菜单,list_menu_ids 是否返回该 menu_id。
按钮不显示 查 v-permission 编码是否在 /menu_permission/list 返回值里。
按钮显示但接口 401 查 menu_permission.uri、method 是否与真实请求匹配,角色是否拥有该按钮权限。
管理员可见,普通角色不可见 这是正常差异;管理员前端和后端都会走放行逻辑。

检查题

问题:新增删除按钮,只在 Vue 页面加 v-permission 是否足够?

答案:不够。

为什么:v-permission 只控制按钮显示,接口访问还要靠 menu_permission.uri + method 和角色授权通过后端 AuthFilter 校验。


Doc 4 技术实现 2 文件上传与富文本安全 (`doc/4-技术实现/2-文件上传与富文本安全.md`)

文件上传与富文本安全

当前文件上传主要由 mall4cloud-biz 的 OSS/MinIO 能力承接,富文本展示在前端通过 DOMPurify 做清洗。

MinIO 上传链路

核心类:

  • OssController
  • OssConfig
  • MinioTemplate

常见流程:

  1. 前端请求 /mall4cloud_biz/oss/info?fileNum=... 获取上传地址。
  2. 后端根据 biz.oss.* 配置创建 MinIO 预签名上传 URL。
  3. 前端上传到 MinIO。
  4. 前端展示图片时使用 VITE_APP_RESOURCES_URL 拼接资源路径。

也存在 /oss/upload_minio 由后端接收文件再上传 MinIO 的接口。

两种方式的区别:/oss/info 是前端拿预签名地址后直传 MinIO,服务端不转发文件内容;/oss/upload_minio 是文件先进业务服务再写入 MinIO,会多占一次服务端流量,适合少量或需要后端介入处理的文件。

必须对齐的配置

配置 示例
Nacos biz.oss.endpoint http://<MinIO-IP>:9000
Nacos biz.oss.resources-url http://<MinIO-IP>:9000/mall4cloud
Nacos biz.oss.bucket mall4cloud
Nacos biz.oss.type 1 表示 MinIO
前端 VITE_APP_RESOURCES_URL http://<MinIO-IP>:9000/mall4cloud
前端 VITE_APP_RESOURCES_TYPE 1

Compose 初始化 SQL 中的 biz.oss.access-key-secret 是 80jpnH4.r5g,与 MINIO_ROOT_PASSWORD 一致。如果 Docker Compose 中 MinIO root 密码改了,Nacos 里的 biz.oss.access-key-secret 也要同步。

富文本安全

当前平台端和商家端有 src/directive/rich 指令,使用 DOMPurify.sanitize 后再写入 HTML。商品详情等富文本展示应使用 v-rich,不要直接 v-html 展示未清洗内容。

后端没有在本轮核对到统一 XSS 过滤器,因此不要把“后端已统一清洗所有输入”写进文档或作为安全假设。

检查题

问题:图片上传成功但页面不显示,是否一定是后端上传失败?

答案:不一定。

为什么:上传成功只说明对象写入了 MinIO。展示还依赖桶策略、resources-url、前端 VITE_APP_RESOURCES_URL 和对象路径拼接。

问题:富文本展示能直接用 v-html 吗?

答案:不要直接用,优先使用项目已有 v-rich。

为什么:v-rich 会先经过 DOMPurify 清洗,直接 v-html 会绕开当前前端安全处理。


Doc 4 技术实现 3 分页验证异常与事务 (`doc/4-技术实现/3-分页验证异常与事务.md`)

分页、验证、异常与事务

这几个机制是后台 CRUD 二开最常用的公共能力。

分页

核心类:

  • PageDTO
  • PageVO
  • PageUtil

Controller 通常接收 @Valid PageDTO pageDTO。PageDTO 要求 pageNum、pageSize 非空,并把最大 pageSize 限制为 500。排序字段会校验字段名,只允许字母、数字、下划线,再把驼峰转下划线。

Service 里常见写法是:

java
PageUtil.doPage(pageDTO, () -> mapper.list(...))

返回给前端的是 PageVO:pages、total、list。

常用对象命名按当前代码理解:

名称 当前用法
Model/PO 与数据库表结构对应,放在 model 目录
DTO 前端传入参数,例如 PageDTO、SpuDTO
VO 返回给前端的数据,例如 PageVO
BO 服务内部或跨服务传递的业务对象

当前前端是 Vue 3,不使用 Vue 2 的 .sync 写法;页面交互以现有 Vue 3 页面和组件为准。

验证

DTO 字段使用 Jakarta Validation 注解,例如 @NotNull、@NotBlank。Controller 参数上加 @Valid 后,验证失败会进入统一异常处理。

统一异常

DefaultExceptionHandlerConfig 处理:

异常 返回
MethodArgumentNotValidException、BindException METHOD_ARGUMENT_NOT_VALID,并返回字段错误列表
HttpMessageNotReadableException HTTP_MESSAGE_NOT_READABLE
Mall4cloudException 使用异常自带枚举或直接显示消息
其他 Exception EXCEPTION,并在存在 Seata XID 时尝试回滚全局事务

项目约定:请求到达服务并被业务处理后,大多数失败也返回 HTTP 200,前端按业务 code 判断。

分布式事务

跨服务写操作参考已有 @GlobalTransactional。典型位置包括订单、商品、平台用户、商家用户等服务。不要只在本地方法上加事务就认为跨服务一致性已经解决。

Redis 锁

公共缓存模块提供 RedisLockRegistry,锁前缀为 spring-cloud。需要并发控制时优先看是否已有业务模式可复用。

检查题

问题:列表接口返回值应该是裸 List<T> 还是 PageVO<T>?

答案:后台分页列表应该返回 PageVO<T>。

为什么:当前分页公共模型包含 pages、total、list,前端分页组件依赖这些字段。

问题:pageSize=10000 会照单全查吗?

答案:不会按 10000 查,PageDTO 会把超过 500 的分页大小限制为 500。

为什么:PageDTO.setPageSize 中有 MAX_PAGE_SIZE = 500 的保护。


Doc 4 技术实现 4 消息搜索与库存链路 (`doc/4-技术实现/4-消息搜索与库存链路.md`)

消息、搜索与库存链路

这部分用于理解消息、搜索和库存协作,先阅读再改造。

RocketMQ

当前代码中可见的消息用途包括:

  • 订单取消后解锁库存。
  • 支付通知后触发订单和库存后续处理。
  • Canal 变更消息驱动搜索索引更新。

注意:提交订单时的初次库存锁定不是 RocketMQ 触发,而是订单服务通过 SkuStockLockFeignClient.lock 调商品服务完成。RocketMQ 主要负责延迟取消、延迟解锁和支付成功后的后续通知。

相关入口:

  • mall4cloud-order 的 RocketMQ 配置和订单监听器。
  • mall4cloud-product 的库存锁定和解锁监听器。
  • mall4cloud-search 的 Canal 监听器。

Elasticsearch

搜索服务依赖 Elasticsearch。索引 mapping 在仓库根目录:

商品发布后列表或搜索没有数据时,不要只看商品库,还要检查 Canal、RocketMQ、Elasticsearch 三段是否正常。

Canal 当前监听配置在中间件目录的 canal/conf 下:instance.properties 指向 MySQL binlog,canal.properties 指向 RocketMQ namesrv,topic 是 canal-topic。搜索服务通过 CanalListener 消费 RocketMqConstant.CANAL_TOPIC,再分发到商品、店铺、分类、品牌、订单等监听器。

不要用 update mall4cloud_product set update_time = now() 触发同步;当前表结构没有这个表名。需要按 canal.instance.filter.regex 里的表名触发,例如 spu、sku、sku_stock、order 等。

库存锁定

核心表:

  • sku_stock
  • sku_stock_lock

下单链路会涉及订单服务和商品服务协作。sku_stock_lock 通过 spu_id + sku_id + order_id 保证同一订单同一 SKU 的锁定记录唯一。

检查题

问题:商品库里有商品,但搜索列表没有数据,最可能只查 MySQL 吗?

答案:不够。

为什么:搜索列表依赖 Elasticsearch 索引,索引更新又可能依赖 Canal 和 RocketMQ。MySQL 有数据只能证明源数据存在。

问题:为什么不要第一个二开功能就选择库存扣减?

答案:因为它横跨订单、商品、消息、事务和库存锁定,风险高。

为什么:学习分层时应先选后台 CRUD,避免一开始就碰交易一致性。


Doc 5 二次开发 1 后台管理功能二开示例 (`doc/5-二次开发/1-后台管理功能二开示例.md`)

后台管理功能二开示例

本示例选择“平台公告管理”作为学习题材。它是后台 CRUD,不直接触碰订单、支付、库存、结算。本页只写教程和检查清单,不在仓库中新增业务代码。

目标

做一个平台端公告管理:

  • 列表查询公告。
  • 新增公告。
  • 编辑公告。
  • 删除或禁用公告。
  • 平台端菜单可见。
  • 普通角色只有授权后才能看到按钮和访问接口。

后端步骤

步骤 应该做什么 验收
建表 在平台业务库新增公告表,包含主键、标题、内容、状态、排序、创建/更新时间 表能初始化,字段含义明确
Model 新增与表对应的 Model 字段类型和数据库一致
DTO 新增保存/更新入参 DTO 必填字段有验证注解
VO 新增列表和详情返回 VO 不把不需要的内部字段暴露给前端
Mapper/XML 写分页列表、详情、新增、更新、删除或改状态 SQL SQL 字段名和表字段一致
Service 封装业务逻辑 Controller 不直接写 SQL
Controller 提供 page、get、save、update、delete 接口 返回 ServerResponseEntity
分页 列表使用 PageDTO 和 PageVO 前端能拿到 total 和 list

接口路径放在平台端语义下,例如 /platform/notice,或采用现有平台模块风格。落地前先参考 HotSearchController、IndexImgController、SysUserController 等后台接口。

前端步骤

步骤 应该做什么 验收
API 在 src/api 下新增公告接口文件 请求都走网关前缀
列表页 在 src/views/modules/platform/notice 下新增页面 能查询、分页、重置
表单弹窗 新增或复用 add-or-update 组件 新增和编辑共用校验
按钮权限 新增、编辑、删除按钮加 v-permission 无权限用户按钮不可见
环境变量 不新增 VUE_APP_* 仍使用 VITE_APP_BASE_API

菜单和按钮权限

需要在 rbac 中配置:

类型 示例
菜单 menu.path = notice,menu.component = platform/notice
新增按钮 platform:notice:save,POST /platform/notice
编辑按钮 platform:notice:update,PUT /platform/notice
删除按钮 platform:notice:delete,DELETE /platform/notice

编码只是示例,落地命名要和现有平台端权限风格保持一致。

验收清单

  • 平台管理员能看到公告菜单。
  • 普通角色未授权时看不到菜单。
  • 普通角色授权菜单后能看到菜单。
  • 未授权按钮权限时,新增/编辑/删除按钮不显示。
  • 直接请求未授权接口会被后端拒绝。
  • 列表分页返回 PageVO。
  • 表单必填项缺失时返回统一验证错误。

检查题

问题:这个示例为什么选公告管理,而不是订单退款?

答案:公告管理是后台 CRUD,能覆盖分层、分页、表单、菜单和按钮权限;订单退款涉及交易一致性,不适合作为第一课。

为什么:学习的目标是先掌握项目模式,再进入高风险业务。


Doc 5 二次开发 2 命名约定与验收清单 (`doc/5-二次开发/2-命名约定与验收清单.md`)

命名约定与验收清单

新功能要像项目原生功能,而不是单独长出来的一套风格。

命名约定

对象 约定
数据库表 下划线命名,如 notice、notice_item
主键 xxx_id 或同业务已有风格
Java 类 NoticeController、NoticeService、NoticeMapper、NoticeDTO、NoticeVO
前端目录 放到 src/views/modules/<业务域>/<功能>
API 文件 放到 src/api/<业务域>
权限编码 <业务域>:<功能>:<动作>
接口路径 跟当前 Controller 风格一致,不混用多个前缀

后端验收

  • Controller 返回 ServerResponseEntity。
  • 新增/更新入参使用 DTO,并对必填字段加验证。
  • 列表使用 PageDTO、PageVO。
  • Service 负责业务编排,Mapper 只做数据访问。
  • 涉及跨服务写操作时评估是否需要 @GlobalTransactional。
  • 接口路径和 HTTP 方法能与 menu_permission 对上。

前端验收

  • 请求走 VITE_APP_BASE_API 指向网关。
  • 页面路径能被 menu.component 动态加载。
  • 按钮使用 v-permission。
  • 列表、表单、删除确认、加载态、错误提示与现有页面风格一致。
  • 不新增 VUE_APP_* 或 Vue 2/Vue CLI 配置。

权限验收

  • 管理员可见全部菜单和按钮。
  • 普通角色只在授权后可见菜单。
  • 普通角色只在授权后可见按钮。
  • 直接调用未授权接口也不能成功。

检查题

问题:权限编码写成 notice:add 可以吗?

答案:不要,除非当前业务域已有这种风格。

为什么:项目现有编码多是 <业务域>:<功能>:<动作>,例如 product:category:save。统一风格方便维护和排查。


Doc 6 核心业务 1 商品订单库存阅读路线 (`doc/6-核心业务/1-商品订单库存阅读路线.md`)

商品、订单、库存阅读路线

核心业务先读请求链路,不急着改交易逻辑。

商品

从 mall4cloud-product 开始:

  1. 分类和品牌决定商品基础归属。
  2. spu 保存商品主信息。
  3. sku 保存具体规格和价格。
  4. sku_stock 保存库存。
  5. 商品搜索还会进入 mall4cloud-search 和 Elasticsearch。

订单

从 mall4cloud-order 开始:

  1. /a/order/confirm 根据立即购买或购物车结算组装购物项,按店铺拆分并计算金额,同时把确认结果和防重复提交标记写入 Redis。
  2. /a/order/submit 从缓存取确认结果,校验未过期且未重复提交后保存订单、订单项和收货地址快照。
  3. 提交订单后通过 SkuStockLockFeignClient.lock 锁定库存,并发送 ORDER_CANCEL_TOPIC 延迟消息;CANCEL_ORDER_DELAY_LEVEL = 16,对应 RocketMQ 30 分钟延迟级别。
  4. sku_stock_lock 保存锁定记录,商品服务还会发送比取消订单晚一级的库存解锁延迟消息。
  5. 支付入口是 /mall4cloud_payment/pay/order。当前代码会创建 pay_info,再直接调用 PayNoticeController.submit 模拟支付成功,然后通过 ORDER_NOTIFY_TOPIC 通知订单服务、通过 ORDER_NOTIFY_STOCK_TOPIC 通知商品服务扣减实际库存。

这里有一个代码风险:PayController 里仍硬编码了 http://192.168.1.17:8126/mall4cloud_payment 作为回调前缀,Nacos 里也存在 application.domainUrl 配置项。接入第三方支付前,要先把回调域名配置收口,不能直接当成生产可用配置。

库存

库存不是简单减字段。当前项目有 sku_stock_lock 锁定记录,订单、商品服务、RocketMQ、Seata 都可能参与。

检查题

问题:学习二开时,为什么不先改订单状态流?

答案:订单状态流牵涉支付、库存、消息和事务,风险比普通后台配置功能高很多。

为什么:一个状态字段变化可能要求多个服务和多张表保持一致,适合作为后续专题,不适合作为第一天练习。


Doc 7 数据模型 1 数据库阅读路线 (`doc/7-数据模型/1-数据库阅读路线.md`)

数据库阅读路线

读数据库不要从所有表平铺开始。先读能解释“登录、菜单、商品、订单”的表。

第一步:登录和权限

先读:

  • mall4cloud_auth.auth_account
  • mall4cloud_rbac.menu
  • mall4cloud_rbac.menu_permission
  • mall4cloud_rbac.role
  • mall4cloud_rbac.role_menu
  • mall4cloud_rbac.user_role
  • mall4cloud_platform.sys_user
  • mall4cloud_multishop.shop_user

这组表能解释:谁登录、属于平台还是商家、看见哪些菜单、拥有哪些按钮权限。

第二步:商品和 SKU

再读:

  • mall4cloud_product.spu
  • mall4cloud_product.sku
  • mall4cloud_product.sku_stock
  • mall4cloud_product.sku_stock_lock
  • mall4cloud_product.spu_attr_value
  • mall4cloud_product.spu_sku_attr_value
  • mall4cloud_product.category
  • mall4cloud_product.brand

这组表能解释:商品主信息、具体 SKU、库存、销售属性、分类和品牌。

第三步:订单

再读:

  • mall4cloud_order.order
  • mall4cloud_order.order_item
  • mall4cloud_order.order_addr

这组表能解释:订单头、订单明细和收货地址快照。

第四步:二开建表习惯

新表优先沿用这些习惯:

  • 主键使用 bigint,字段名用下划线。
  • 常见字段包含 create_time、update_time。
  • 多端或多店铺数据要考虑 shop_id、tenant_id、user_id。
  • 状态字段要明确枚举值,例如 1:enable, 0:disable, -1:deleted。
  • 软删除不是全表统一字段,需先看同业务域已有表如何处理。
  • Seata 参与的库有 undo_log。

检查题

问题:为什么权限表应该先读,而不是最后读?

答案:后台二开离不开菜单、按钮和接口权限,权限表决定新页面能不能被看见、按钮能不能显示、接口能不能访问。

为什么:前端动态路由、v-permission、后端 AuthFilter 都依赖 rbac 表。


Doc 7 数据模型 2 权限商品订单核心表 (`doc/7-数据模型/2-权限商品订单核心表.md`)

权限、商品、订单核心表速查

本页只讲启动和二开最常用的表。

权限表

表 作用 关键字段
auth_account 统一账号 username、password、sys_type、user_id、tenant_id、is_admin
menu 后台菜单和动态路由 menu_id、parent_id、biz_type、path、component
menu_permission 按钮和接口权限 permission、uri、method、menu_id、biz_type
role 角色 role_id、biz_type、tenant_id
role_menu 角色拥有的菜单和按钮 role_id、menu_id、menu_permission_id
user_role 用户拥有的角色 user_id、role_id

sys_type 和 biz_type 的常见含义:1 商家端,2 平台端。

商品表

表 作用 关键字段
spu 商品主信息 spu_id、brand_id、category_id、shop_id、name、status
sku 具体销售 SKU sku_id、spu_id、sku_name、attrs、price_fee、status
sku_stock SKU 库存 sku_id、actual_stock、lock_stock、stock
sku_stock_lock 下单库存锁定 spu_id、sku_id、order_id、status、count
spu_detail 商品详情 spu_id、detail
spu_sku_attr_value SKU 销售属性 spu_id、sku_id、attr_name、attr_value_name

价格字段如 price_fee 用整数保存,二开时不要随意改成浮点金额。

订单表

表 作用 关键字段
order 订单主表 order_id、shop_id、user_id、total、status、is_payed
order_item 订单商品明细 order_id、spu_id、sku_id、count、price、spu_total_amount
order_addr 收货地址快照 order_addr_id、user_id、consignee、mobile、addr
pay_info 支付记录 pay_id、user_id、pay_amount、pay_status、order_ids、version

订单状态当前 SQL 注释中说明:1 待付款,2 待发货,3 待收货,5 成功,6 失败。

订单主表中以下字段在读订单状态时需要一起看:

字段 含义
close_type 订单关闭原因,SQL 注释含 1 超时未支付、4 买家取消、15 货到付款交易
delete_status 用户侧删除状态:0 未删除、1 回收站、2 永久删除
version 订单版本号,SQL 注释为每处理一次订单版本号加一
order_addr_id 指向 order_addr,保存下单时的收货地址快照

关系速记

  • 一个账号 auth_account 通过 sys_type + user_id 指向平台用户或商家用户。
  • 一个用户通过 user_role 拥有多个角色。
  • 一个角色通过 role_menu 拥有菜单和按钮权限。
  • 一个商品 spu 有多个 sku,每个 sku 对应库存。
  • 一个订单 order 有多个 order_item,每个明细记录当时的 spu_id、sku_id、价格和数量。
  • 一个订单保存一个 order_addr_id,避免用户后续修改地址影响已下单记录展示。

检查题

问题:前端按钮权限编码应该去哪个表找?

答案:mall4cloud_rbac.menu_permission.permission。

为什么:前端 v-permission 使用的就是这个编码,后端接口权限也用它匹配用户权限。


Doc 7 数据模型 3 带答案的表结构检查题 (`doc/7-数据模型/3-带答案的表结构检查题.md`)

带答案的表结构检查题

这些题不是考试,是帮助读者确认自己已经读懂关键关系。

权限

问题:一个普通平台用户登录后,为什么可能看不到某个菜单?

答案:因为用户不是管理员时,前端会根据 /menu/list_menu_ids 返回的菜单 ID 过滤动态路由;如果角色没有关联该菜单,菜单就不会显示。

为什么:用户通过 user_role 找到角色,角色通过 role_menu.menu_id 拥有菜单,前端再用这些菜单 ID 过滤 menu 路由。

问题:按钮显示和接口放行是不是同一件事?

答案:不是。

为什么:按钮显示由前端 v-permission 判断 menu_permission.permission;接口放行由后端根据 menu_permission.uri + method 和用户权限判断。

商品

问题:SPU 和 SKU 的区别是什么?

答案:SPU 是商品主信息,SKU 是具体可销售规格。

为什么:spu 保存商品名称、店铺、分类、上下架状态;sku 保存 spu_id、规格属性、价格和 SKU 状态。

问题:库存为什么不只放在 sku 表?

答案:库存独立放在 sku_stock,锁定记录放在 sku_stock_lock。

为什么:库存会被下单、取消、支付等链路频繁改变,独立表和锁定表便于处理可售库存、实际库存、锁定库存和订单锁定记录。

订单

问题:订单明细为什么要保存商品名称、SKU 名称和价格?

答案:因为订单需要保留下单时的商品快照。

为什么:商品后续可能改名、改价或下架,order_item 仍要展示和结算下单时的信息。

问题:订单表里的 total 和订单项里的 spu_total_amount 可以直接改成小数吗?

答案:不要。

为什么:当前金额字段以整数保存,随意改成小数会影响支付、结算、前后端展示和已有数据。

二开

问题:新增“公告管理”表是否一定要有 shop_id?

答案:不一定,要看公告是平台全局还是店铺独立。

为什么:平台全局公告可以归平台端管理;店铺独立公告才需要 shop_id 或租户维度。建表前先明确数据归属。

问题:新表一定要有 undo_log 吗?

答案:新业务表本身不需要 undo_log 字段;参与 Seata 分布式事务的数据库需要有独立的 undo_log 表。

为什么:undo_log 是 Seata AT 模式使用的事务回滚表,不是每张业务表的字段。


Doc 8 部署运维 1 部署路径与上线检查 (`doc/8-部署运维/1-部署路径与上线检查.md`)

部署路径与上线检查

部署前先区分三种路径。

路径一:本地开发

适合二开:

  1. 本地或服务器启动中间件。
  2. IDEA 启动后端服务。
  3. pnpm dev 启动平台端或商家端。
  4. 前端 VITE_APP_BASE_API 指向网关 8000。

路径二:单机服务器中间件 + 本地代码

适合团队共享中间件:

  1. 服务器用 中间件 Docker Compose 启动 MySQL、Redis、Nacos 等。
  2. 本地服务通过 NACOS_HOST 指向服务器。
  3. 前端资源地址指向服务器 MinIO。

路径三:生产部署

生产部署需要额外确认:

  • Nacos、Redis、MySQL、MinIO、RocketMQ、Elasticsearch 不应直接暴露公网。
  • RocketMQ dashboard 当前未配置登录保护,不能裸露。
  • 前端构建后由 Nginx 提供静态资源。
  • 前端 API 地址要指向生产网关域名。
  • MinIO 桶策略和资源域名要按生产安全要求配置。

Nginx 注意点

平台端和商家端当前仓库内的 nginx.conf 只配置了静态资源根目录,没有代理后端 API。生产环境更常见做法是:

  • 静态资源由 Nginx 服务。
  • API 通过 VITE_APP_BASE_API 指向网关域名。
  • 或在外层 Nginx 单独配置 API 反向代理。

不要假设前端工程里的 Nginx 配置已经覆盖生产代理。

上线检查

检查项 正确结果
网关 8000 或生产域名可访问
Nacos 服务已注册,配置可读取
MySQL 业务库、Nacos 库、Seata 库存在
Redis 密码和 Nacos 配置一致
MinIO 桶存在,资源地址可访问
前端 VITE_APP_BASE_API 指向网关
登录 平台端或商家端能登录
权限 普通角色权限符合预期
日志 后端错误能在对应服务日志中定位

检查题

问题:生产环境只改前端 .env.production 就够了吗?

答案:不够。

为什么:还要核对 Nacos 中数据源、Redis、OSS、RocketMQ、Seata、网关路由,以及中间件自身的网络和安全暴露。


Doc 8 部署运维 3 已知风险与待核对项 (`doc/8-部署运维/3-已知风险与待核对项.md`)

已知风险与待核对项

这页记录不能直接按生产配置使用的内容。

已知风险

风险 当前处理
Docker 安装教程过于通用 本文不展开,按 Docker 官方文档安装
部分截图可能和当前 UI 不完全一致 只作为操作界面参考,不作为验证依据
前端环境变量 当前必须使用 VITE_APP_*
RocketMQ dashboard 未配置登录保护 生产环境不要公网暴露
Seata 控制台 当前 Seata 2.6 compose 只使用 8091
Nacos 默认账号 本目录初始化 SQL 写入 nacos / 80jpnH4.r5g,而部分服务 bootstrap 默认值仍写着 nacos/nacos;如果启用 Nacos 鉴权,必须把两边统一
搜索同步 SQL update mall4cloud_product set update_time = now()、update mall4cloud_order set update_time = now() 不匹配当前表名,不能照搬
支付回调地址 PayController 当前仍硬编码网关地址,支付专题前不能把它写成生产可用配置

当前未展开的内容

  • 移动端/小程序源码结构。
  • 订单退款、支付、结算、库存扣减的二开教程。
  • 生产级高可用部署。
  • 商业授权和企业版本差异的技术交付细节。

这些内容需要单独设计和验证,不放在启动文档里。

检查题

问题:未经验证的命令,可以直接照搬吗?

答案:不可以。

为什么:当前项目使用 Spring Boot 4、Vue 3、Vite、pnpm,命令必须和当前仓库配置一致。


Doc 9 故障排查 1 启动登录接口常见问题 (`doc/9-故障排查/1-启动登录接口常见问题.md`)

启动、登录、接口常见问题

先按现象排查,不要一上来改代码。

服务连不上 Nacos

答案:先核对 NACOS_HOST、NACOS_PORT,再看 Nacos 容器、控制台和客户端端口。

为什么:各服务默认 Nacos 地址是 ${NACOS_HOST:192.168.1.46}:${NACOS_PORT:8848},如果你的环境不是这个 IP,就要改环境变量或启动配置。当前 Compose 的 Nacos v3 控制台是 8080,服务客户端主要看 8848,同时要放开 9848、9849。

排查顺序:

  1. 在服务器执行 docker ps -a,确认 mall4cloud-nacos 没有反复重启。
  2. 用 docker logs -f mall4cloud-nacos 看是否 MySQL 连接、账号或初始化库错误。
  3. 打开 http://:8080/index.html,确认能登录控制台。
  4. 在配置列表里确认 application.yml、mall4cloud-gateway.yml 等配置存在。
  5. 如果 Nacos 配置已改但服务仍读到缓存地址,重启 Nacos 容器后再重启 Java 服务。

前端登录请求 404

答案:先核对 VITE_APP_BASE_API 是否指向网关 8000,不是某个业务服务端口。

为什么:前端接口带 /mall4cloud_auth、/mall4cloud_rbac 等前缀,网关负责按前缀转发。

前端请求 503

答案:先查网关路由目标服务是否启动并注册到 Nacos。

为什么:503 常见于网关能收到请求,但后面的 auth、rbac、platform、multishop、biz 等服务没有可用实例。

前端登录返回未授权

答案:检查账号密码、auth 服务、Redis、数据库初始化是否一致。

为什么:登录依赖 mall4cloud_auth.auth_account,Token 校验依赖 auth 服务和 Redis。

滑动验证码加载或校验失败

答案:先用浏览器 F12 的 Network 看验证码接口请求,再查 Redis。

为什么:验证码校验依赖 Redis。Redis 未启动、密码不一致,或 Nacos application.yml 中 Redis 地址仍指向错误 IP,都会导致验证码正常显示但校验失败。

登录后菜单不显示

答案:先判断用户是否管理员;非管理员再查角色是否拥有菜单。

为什么:非管理员会通过 list_menu_ids 获取菜单 ID,前端只显示这些 ID 对应的路由。

按钮不显示

答案:查按钮上的 v-permission 编码是否存在于用户权限列表。

为什么:前端 src/directive/permission 会从用户 store 的 roles 里查编码,没有就移除按钮。

接口 401 或权限失败

答案:查 Authorization 请求头、Token 是否过期、menu_permission.uri 和 method 是否匹配。

为什么:后端 AuthFilter 先校验 Token,再校验平台端/商家端 RBAC 权限。

图片不显示

答案:核对 MinIO 桶、桶策略、Nacos biz.oss.resources-url、前端 VITE_APP_RESOURCES_URL。

为什么:上传、返回路径、前端拼接地址、桶读取权限任何一处错都会导致图片不可见。

商品发布后搜索不到

答案:除 MySQL 外,还要查 Canal、RocketMQ、Elasticsearch。

为什么:搜索列表依赖 ES 索引,索引更新链路不等于商品表写入成功。

排查顺序:

  1. MySQL 执行 SHOW MASTER STATUS,确认 binlog 可读。
  2. 检查 canal/conf/example/instance.properties 中 MySQL 地址、mysql-binlog.* 文件名、canal 账号密码。
  3. 检查 canal/conf/canal.properties 中 rocketmq.namesrv.addr。
  4. 看 canal/logs/example/example.log 是否还在报错。
  5. 看 RocketMQ dashboard 是否收到 canal-topic。
  6. 看 mall4cloud-search 是否消费 canal-topic,ES 中是否已创建 product、order mapping。

RocketMQ 无法发送 topic

答案:遇到 No route info of this topic: stock-unlock-topic,先查 RocketMQ broker 配置挂载和目录权限。

为什么:一种常见情况是 broker 没读到挂载的配置,导致 topic 路由不符合项目预期。当前中间件目录要求启动前给 rocketmq/ 目录足够权限。

Seata 连接失败

答案:先核对 seata/application.yml 的 MySQL 地址和 application.yml 中 seata.service.grouplist.default。

为什么:当前 Seata 2.6 compose 只暴露 8091,本仓库没有使用 7091 控制台配置。

检查题

问题:跨域报错时,第一反应是改业务 Controller 吗?

答案:不是,先查网关和前端 API 地址。

为什么:跨域主要发生在浏览器访问网关时,Nacos 中网关配置包含 CORS 规则,前端也必须请求正确网关地址。


Doc 8 部署运维 2 中间件 Docker Compose Docker Compose Native.Yaml (`doc/8-部署运维/2-中间件-docker-compose/docker-compose-native.yaml`)

version: "3.5"

services:
mall4cloud-mysql:
image: mysql:8.0
container_name: mall4cloud-mysql
restart: always
environment:
- MYSQL_ROOT_PASSWORD=80jpnH4.r5g
network_mode: "host"
expose:
- 3306
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/conf.d:/etc/mysql/conf.d
- ./mysql/initdb:/docker-entrypoint-initdb.d

mall4cloud-minio:
image: minio/minio:RELEASE.2024-04-18T19-09-19Z
container_name: mall4cloud-minio
restart: always
command: server /data --console-address ":9001"
network_mode: "host"
expose:
- 9000
- 9001
volumes:
- ./minio/data:/data
environment:
- MINIO_ROOT_USER=admin
- MINIO_ROOT_PASSWORD=80jpnH4.r5g
- MINIO_BROWSER_REDIRECT_URL=http://192.168.1.46:9001

mall4cloud-redis:
image: redis:7.0
container_name: mall4cloud-redis
restart: always
network_mode: "host"
command: redis-server --requirepass 80jpnH4.r5g
expose:
- 6379

mall4cloud-nacos:
image: nacos/nacos-server:v3.1.1
container_name: mall4cloud-nacos
restart: always
depends_on:
- mall4cloud-mysql
network_mode: "host"
expose:
- 8848
- 9848
- 9849
- 8080
environment:
- JVM_XMS=256m
- JVM_XMX=256m
- MODE=standalone
- PREFER_HOST_MODE=hostname
- SPRING_DATASOURCE_PLATFORM=mysql
- MYSQL_SERVICE_HOST=192.168.1.46
- MYSQL_SERVICE_DB_NAME=mall4cloud_nacos
- MYSQL_SERVICE_USER=root
- MYSQL_SERVICE_PASSWORD=80jpnH4.r5g
- NACOS_AUTH_ENABLE=true
- NACOS_AUTH_TOKEN=TWFsbDRqTWFsbDRjbG91ZE1hbGw0ak1hbGw0Y2xvdWRNYWxsNGpNYWxsNGNsb3Vk
- NACOS_AUTH_IDENTITY_KEY=mall4jmall4jmall4jmall4jmall4jmall4jmall4jmall4j
- NACOS_AUTH_IDENTITY_VALUE=mall4cloudmall4cloudmall4cloudmall4cloudmall4cloudmall4cloudmall4cloud
volumes:
- ./nacos/logs:/home/nacos/logs

mall4cloud-seata:
image: apache/seata-server:2.6.0
container_name: mall4cloud-seata
restart: always
network_mode: "host"
expose:
- 8091
environment:
- TZ
- STORE_MODE=db
- SEATA_IP=192.168.1.46
- SEATA_PORT=8091
volumes:
- ./seata/application.yml:/seata-server/resources/application.yml

mall4cloud-elasticsearch:
image: elasticsearch:7.17.21
container_name: mall4cloud-elasticsearch
restart: always
network_mode: "host"
expose:
- 9200
- 9300
environment:
- discovery.type=single-node
- ES_JAVA_OPTS=-Xms512m -Xmx512m
- ELASTICSEARCH_USERNAME=elastic
- ELASTIC_PASSWORD=80jpnH4.r5g
- xpack.security.enabled=true
volumes:
- ./elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
- ./elasticsearch/data:/usr/share/elasticsearch/data
- ./elasticsearch/plugins:/usr/share/elasticsearch/plugins

mall4cloud-canal:
image: canal/canal-server:v1.1.7
container_name: mall4cloud-canal
restart: always
network_mode: "host"
expose:
- 11111
volumes:
- ./canal/conf/example:/home/admin/canal-server/conf/example
- ./canal/conf/canal.properties:/home/admin/canal-server/conf/canal.properties
- ./canal/logs:/home/admin/canal-server/logs

mall4cloud-rocketmq-namesrv:
image: apache/rocketmq:5.2.0
container_name: mall4cloud-rocketmq-namesrv
restart: always
network_mode: "host"
expose:
- 9876
volumes:
- ./rocketmq/namesrv/logs:/home/rocketmq/logs
- ./rocketmq/namesrv/store:/home/rocketmq/store
environment:
JAVA_OPT_EXT: "-Duser.home=/home/rocketmq -Xms512M -Xmx512M -Xmn128M"
command: ["sh","mqnamesrv"]

mall4cloud-rocketmq-broker:
image: apache/rocketmq:5.2.0
container_name: mall4cloud-rocketmq-broker
restart: always
network_mode: "host"
expose:
- 10909
- 10911
volumes:
- ./rocketmq/broker/logs:/home/rocketmq/logs
- ./rocketmq/broker/store:/home/rocketmq/store
- ./rocketmq/broker/conf/broker.conf:/etc/rocketmq/broker.conf
environment:
JAVA_OPT_EXT: "-Duser.home=/home/rocketmq -Xms512M -Xmx512M -Xmn128M -XX:-AssumeMP"
command: ["sh","mqbroker","-c","/etc/rocketmq/broker.conf","-n","192.168.1.46:9876","autoCreateTopicEnable=true"]
depends_on:
- mall4cloud-rocketmq-namesrv

mall4cloud-rocketmq-dashboard:
image: fsckzy01/rocketmq-dashboard:1.0.1
container_name: mall4cloud-rocketmq-dashboard
restart: always
ports:
- 8180:8082
environment:
JAVA_OPTS: "-Drocketmq.namesrv.addr=192.168.1.46:9876 -Dcom.rocketmq.sendMessageWithVIPChannel=false"
depends_on:
- mall4cloud-rocketmq-namesrv


Doc 8 部署运维 2 中间件 Docker Compose Docker Compose.Yaml (`doc/8-部署运维/2-中间件-docker-compose/docker-compose.yaml`)

version: "3.5"

services:
mall4cloud-mysql:
image: registry.cn-hongkong.aliyuncs.com/mall4j-images/mysql:8.0.35
container_name: mall4cloud-mysql
restart: always
environment:
- MYSQL_ROOT_PASSWORD=80jpnH4.r5g
network_mode: "host"
expose:
- 3306
volumes:
- ./mysql/data:/var/lib/mysql
- ./mysql/conf.d:/etc/mysql/conf.d
- ./mysql/initdb:/docker-entrypoint-initdb.d

mall4cloud-minio:
image: registry.cn-hongkong.aliyuncs.com/mall4j-images/minio:RELEASE.2024-04-18T19-09-19Z
container_name: mall4cloud-minio
restart: always
command: server /data --console-address ":9001"
network_mode: "host"
expose:
- 9000
- 9001
volumes:
- ./minio/data:/data
environment:
- MINIO_ROOT_USER=admin
- MINIO_ROOT_PASSWORD=80jpnH4.r5g
- MINIO_BROWSER_REDIRECT_URL=http://192.168.1.46:9001

mall4cloud-redis:
image: registry.cn-hongkong.aliyuncs.com/mall4j-images/redis:7.0
container_name: mall4cloud-redis
restart: always
network_mode: "host"
command: redis-server --requirepass 80jpnH4.r5g
expose:
- 6379

mall4cloud-nacos:
image: registry.cn-hongkong.aliyuncs.com/mall4j-images/nacos-server:v3.1.1
container_name: mall4cloud-nacos
restart: always
depends_on:
- mall4cloud-mysql
network_mode: "host"
expose:
- 8848
- 9848
- 9849
- 8080
environment:
- JVM_XMS=256m
- JVM_XMX=256m
- MODE=standalone
- PREFER_HOST_MODE=hostname
- SPRING_DATASOURCE_PLATFORM=mysql
- MYSQL_SERVICE_HOST=192.168.1.46
- MYSQL_SERVICE_DB_NAME=mall4cloud_nacos
- MYSQL_SERVICE_USER=root
- MYSQL_SERVICE_PASSWORD=80jpnH4.r5g
- NACOS_AUTH_ENABLE=true
- NACOS_AUTH_TOKEN=TWFsbDRqTWFsbDRjbG91ZE1hbGw0ak1hbGw0Y2xvdWRNYWxsNGpNYWxsNGNsb3Vk
- NACOS_AUTH_IDENTITY_KEY=mall4jmall4jmall4jmall4jmall4jmall4jmall4jmall4j
- NACOS_AUTH_IDENTITY_VALUE=mall4cloudmall4cloudmall4cloudmall4cloudmall4cloudmall4cloudmall4cloud
volumes:
- ./nacos/logs:/home/nacos/logs

mall4cloud-seata:
image: registry.cn-hongkong.aliyuncs.com/mall4j-images/seata-server:2.6.0
container_name: mall4cloud-seata
restart: always
network_mode: "host"
expose:
- 8091
environment:
- TZ
- STORE_MODE=db
- SEATA_IP=192.168.1.46
- SEATA_PORT=8091
volumes:
- ./seata/application.yml:/seata-server/resources/application.yml

mall4cloud-elasticsearch:
image: registry.cn-hongkong.aliyuncs.com/mall4j-images/elasticsearch:7.17.21
container_name: mall4cloud-elasticsearch
restart: always
network_mode: "host"
expose:
- 9200
- 9300
environment:
- discovery.type=single-node
- ES_JAVA_OPTS=-Xms512m -Xmx512m
- ELASTICSEARCH_USERNAME=elastic
- ELASTIC_PASSWORD=80jpnH4.r5g
- xpack.security.enabled=true
volumes:
- ./elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
- ./elasticsearch/data:/usr/share/elasticsearch/data
- ./elasticsearch/plugins:/usr/share/elasticsearch/plugins

mall4cloud-canal:
image: registry.cn-hongkong.aliyuncs.com/mall4j-images/canal-server:v1.1.7
container_name: mall4cloud-canal
restart: always
network_mode: "host"
expose:
- 11111
volumes:
- ./canal/conf/example:/home/admin/canal-server/conf/example
- ./canal/conf/canal.properties:/home/admin/canal-server/conf/canal.properties
- ./canal/logs:/home/admin/canal-server/logs

mall4cloud-rocketmq-namesrv:
image: registry.cn-hongkong.aliyuncs.com/mall4j-images/rocketmq:5.2.0
container_name: mall4cloud-rocketmq-namesrv
restart: always
network_mode: "host"
expose:
- 9876
volumes:
- ./rocketmq/namesrv/logs:/home/rocketmq/logs
- ./rocketmq/namesrv/store:/home/rocketmq/store
environment:
JAVA_OPT_EXT: "-Duser.home=/home/rocketmq -Xms512M -Xmx512M -Xmn128M"
command: ["sh","mqnamesrv"]

mall4cloud-rocketmq-broker:
image: registry.cn-hongkong.aliyuncs.com/mall4j-images/rocketmq:5.2.0
container_name: mall4cloud-rocketmq-broker
restart: always
network_mode: "host"
expose:
- 10909
- 10911
volumes:
- ./rocketmq/broker/logs:/home/rocketmq/logs
- ./rocketmq/broker/store:/home/rocketmq/store
- ./rocketmq/broker/conf/broker.conf:/etc/rocketmq/broker.conf
environment:
JAVA_OPT_EXT: "-Duser.home=/home/rocketmq -Xms512M -Xmx512M -Xmn128M -XX:-AssumeMP"
command: ["sh","mqbroker","-c","/etc/rocketmq/broker.conf","-n","192.168.1.46:9876","autoCreateTopicEnable=true"]
depends_on:
- mall4cloud-rocketmq-namesrv

mall4cloud-rocketmq-dashboard:
image: registry.cn-hongkong.aliyuncs.com/mall4j-images/rocketmq-dashboard:1.0.1
container_name: mall4cloud-rocketmq-dashboard
restart: always
ports:
- 8180:8082
environment:
JAVA_OPTS: "-Drocketmq.namesrv.addr=192.168.1.46:9876 -Dcom.rocketmq.sendMessageWithVIPChannel=false"
depends_on:
- mall4cloud-rocketmq-namesrv


Doc 8 部署运维 2 中间件 Docker Compose Seata Application.Yml (`doc/8-部署运维/2-中间件-docker-compose/seata/application.yml`)

spring:
application:
name: seata-server
main:
web-application-type: none

logging:
config: classpath:logback-spring.xml
file:
path: ${user.home}/logs/seata
extend:
logstash-appender:
destination: 127.0.0.1:4560
kafka-appender:
bootstrap-servers: 127.0.0.1:9092
topic: logback_to_logstash

seata:
config:
# support: nacos, consul, apollo, zk, etcd3
type: file
registry:
# support: nacos, eureka, redis, zk, consul, etcd3, sofa
type: file
store:
# support: file 、 db 、 redis
mode: db
db:
datasource: druid
dbType: mysql
# 需要根据mysql的版本调整driverClassName
# mysql8及以上版本对应的driver:com.mysql.cj.jdbc.Driver
# mysql8以下版本的driver:com.mysql.jdbc.Driver
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.1.46:3306/mall4cloud_seata?useUnicode=true&characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&rewriteBatchedStatements=true
user: root
password: 80jpnH4.r5g

server:

service-port: 8091 #If not configured, the default is '${server.port} + 1000'

security:
secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
tokenValidityInMilliseconds: 1800000
ignore:
urls: /,//*.css,//.js,/**/.html,//*.map,//.svg,/**/.png,//*.ico,/console-fe/public/,/api/v1/auth/login


--- METRICS ---