# mate-modulith **Repository Path**: tangsm-demo/mate-modulith ## Basic Information - **Project Name**: mate-modulith - **Description**: No description available - **Primary Language**: Java - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-13 - **Last Updated**: 2026-09-14 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Mate-Cloud · Modulith

Spring Boot Spring Modulith Java MySQL Sa-Token Vue License

以 **[MateCloud](https://gitee.com/matevip/matecloud)**(Spring Cloud Alibaba 微服务脚手架)为业务蓝本,使用 **Spring Modulith 2.1** 重写而成的**模块化单体(Modular Monolith)** 后台管理基座。 > **一份业务,两种强制边界**:Maven 模块提供编译期物理边界,Spring Modulith 应用模块提供运行期/测试期领域边界。 > **模块边界即未来微服务的拆分线**——单体可直接演进为微服务,业务代码无需重写。 --- ## 一、系统说明 **一句话定位**:保留 MateCloud 四个核心服务(网关 / 认证 / 系统管理 / 通知)的全部业务能力与 REST 契约,把「微服务的部署复杂度」换成「模块化单体的边界可验证性」。 核心卖点: | 卖点 | 说明 | | --- | --- | | **可自动校验的模块边界** | `ApplicationModules.of(MateCloudApplication.class).verify()` 强制校验依赖方向、包封装与无环;违反即构建失败 | | **启动期结构校验** | `spring.modulith.runtime.verification-enabled=true`,启动即发现边界违规,不必等到测试 | | **模块感知 Flyway** | 各模块自带 `db/migration//` 迁移脚本,独立版本线 + 独立跟踪表 `flyway_schema_history_`,由 Modulith 按**模块依赖顺序**执行 | | **事件驱动跨模块通信** | 领域事件替代 Dubbo/Feign;Event Publication Registry(JDBC,v2 状态机)持久化未完成事件,崩溃可重发 | | **事件外部化(outbox 语义)** | `@Externalized` + `spring-modulith-events-amqp` 把需要跨进程的事件投递到 MQ,进程内事件走 `@ApplicationModuleListener` | | **零 Nacos / 零 Dubbo / 零 Feign** | 单进程 `java -jar mate-monolith.jar` 启动,仅依赖 MySQL(Redis 可选) | | **前端仓库内复刻** | 对外 REST 契约保持 MateCloud 的 `/api/v1/**` 路径与 `Result{code,msg,data}` 响应体;`mate-ui` 已在本仓库内复刻(Vue 3.5 复刻版,动态路由由后端菜单驱动) | | **DDD 四层 + 领域纯净** | 模块内 `interfaces / application / domain / infrastructure`;ArchUnit 守护 `domain` 包不出现任何 Spring 注解 | | **可观测基线** | `/actuator/modulith` 暴露模块拓扑,`/actuator/events` 暴露事件注册表状态,MDC 贯穿 `traceId / tenantId / userId` | **设计理念**:最小公共(共享内核不膨胀)、各司其职(一个模块一件事)、Starter = 即插即用能力、边界显式且可验证。 --- ## 二、架构全景 ### 2.1 微服务 → 应用模块映射 | MateCloud 微服务 | 端口 | 目标 Modulith 应用模块 | 模块职责 | | --- | --- | --- | --- | | mate-gateway | 9010 | **`mate-gateway`**(可选独立进程,**不进入单体**) | API 路由转发 + 基础限流;**不做 Token 校验** | | mate-auth | 9020 | `auth`(`com.mate.auth`) | 登录认证、Token 管理、验证码/短信/SSO、在线用户、开放接口签名 | | mate-system | 9030 | `system`(`com.mate.system`) | 用户 / 角色 / 菜单 / 部门 / 岗位 / 字典 / 参数 / 租户 / 操作日志 / 登录日志 | | mate-notice | 9050 | `notice`(`com.mate.notice`) | 站内信、邮件、短信、SSE/WebSocket 推送(渠道适配器 SPI) | | mate-ai | — | `ai`(`com.mate.ai`) | Spring AI 对话、`@Tool` 自动发现、会话记忆、流式对话 | | mate-starters(横切) | — | `common` 共享内核 + `mate-starters/*` | 统一响应、异常、租户上下文、缓存、锁、安全装配、事件运维、任务、Excel | | 通用 S3 兼容存储(AWS SDK v2) | — | `file`(`com.mate.file`) | `FileStorageService` 命名接口,LOCAL / 通用 S3 兼容(AWS S3 / 阿里云 OSS / 腾讯云 COS / MinIO / 华为云 OBS / 七牛)多实现 | ### 2.2 模块依赖图 ``` 实线 = 同步 API 依赖(仅允许 via `::api` 命名接口) 虚线 = 领域事件(Event Publication Registry) ``` ```mermaid graph TD common["common · 共享内核(OPEN · sharedModules)
Result / PageResult / BizException / ErrorCode
TenantContextHolder / PageQuery / 通用注解"] subgraph capability["能力模块(CLOSED)"] file["file · 文件存储"] notice["notice · 通知"] ai["ai · AI 对话"] end subgraph business["业务模块(CLOSED)"] auth["auth · 认证"] system["system · 系统管理"] end auth -->|"system :: api"| system auth -->|"notice :: api"| notice system -->|"file :: api"| file auth --> common system --> common notice --> common file --> common ai --> common auth -.->|"UserAuthenticatedEvent"| system system -.->|"UserDisabledEvent / PermissionChangedEvent"| auth system -.->|"NoticeSendEvent"| notice ``` ### 2.3 模块内分层(DDD 四层 + 对外契约包) ``` com.mate./ ├── package-info.java # @ApplicationModule(displayName="中文模块名", type=CLOSED, allowedDependencies={...}) ├── api/ # 【Named Interface "api"】跨模块契约:Api 接口 + DTO + 事件 │ ├── package-info.java # @NamedInterface("api") │ ├── dto/package-info.java # @NamedInterface("api") ← 命名接口不递归包含子包,必须逐包声明 │ └── event/package-info.java# @NamedInterface("api") ├── interfaces/ # 【入站适配器】REST Controller、请求/响应 VO、Assembler、事件监听器 │ ├── rest/ │ └── listener/ ├── application/ # 【用例编排】CommandService(写)/ QueryService(读),@Transactional 边界在此 ├── domain/ # 【领域核心 · 零框架依赖】聚合根、实体、值对象、领域事件、仓储接口、领域服务 └── infrastructure/ # 【出站适配器】仓储实现、Entity、Mapper、外部系统客户端 ``` `common` 共享内核为 `type = OPEN`,其余模块一律 `type = CLOSED`;跨模块只允许 `import` 对方 `api/` 下类型。 --- ## 三、快速开始 ### 3.1 环境要求 | 组件 | 版本 | 说明 | | --- | --- | --- | | JDK | **25+** | Spring Boot 4 无法在 JDK 8/17 下构建 | | Maven | 3.9+ | 建议 3.9.9+ | | MySQL | 8.0(兼容 5.7) | 库名 `mate`,字符集 `utf8mb4` | | Redis | 7+(可选) | 未接入时自动降级为进程内实现 | | Node.js | 18+ | 仅前端 `mate-ui` 需要 | > ⚠️ 本机 `PATH` 默认 JDK 8 时,构建前必须设置 `JAVA_HOME` 指向 JDK 25。 ### 3.2 构建与启动 ```bash # 1. 建库(无需手动导 SQL,Flyway 启动时按模块自动迁移建表) mysql -uroot -p -e "CREATE DATABASE mate DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;" # 2. 全量构建(含模块边界校验 MateCloudModulithTest) mvn clean install # 3. 单进程启动 java -jar mate-monolith/target/mate-monolith-*.jar --server.port=18080 ``` > 端口说明:`application.yml` 默认 `8080`;本机联调惯例用 **18080**(与前端代理默认目标一致)。 ### 3.3 启动前端 ```bash cd mate-ui npm install npm run dev # → http://127.0.0.1:5173,/api 代理到后端(保留 /api/v1 前缀) ``` ### 3.4 访问入口 | 入口 | 地址 | | --- | --- | | 前端管理后台 | http://127.0.0.1:5173 | | Swagger UI | http://localhost:18080/swagger-ui.html | | OpenAPI JSON | http://localhost:18080/v3/api-docs | | 模块拓扑 | http://localhost:18081/actuator/modulith | | 事件注册表 | http://localhost:18081/actuator/events | | 健康检查 | http://localhost:18081/actuator/health | 默认账号:`admin / admin123`(由 `mate-module-system` 的 Flyway 种子脚本写入,BCrypt 加密)。 --- ## 四、核心依赖 | 依赖 | 版本 | 说明 | | --- | --- | --- | | JDK | **25** | Temurin HotSpot | | Spring Boot | **4.1.1** | Spring Framework 7,Jackson 3(`tools.jackson`) | | Spring Modulith | **2.1.1**(GA) | 模块校验 / 事件注册表 / 事件外部化 / 模块感知 Flyway / 启动期校验 | | Spring AI | 2.0.1 | `ai` 模块:ChatClient、`@Tool`、会话记忆、流式对话 | | Sa-Token | 1.46.0 | `sa-token-spring-boot4-starter` + `sa-token-redis-template`(认证鉴权) | | MyBatis-Plus | 3.5.17 | `mybatis-plus-spring-boot4-starter` + `mybatis-plus-jsqlparser` | | Flyway | Boot 4 托管 | `spring-boot-starter-flyway` + `flyway-mysql`,模块感知迁移 | | Redisson | 4.3.1 | `@DistributedLock`、限流、缓存同步 | | Caffeine | 3.x | 权限 L1 本地缓存(L2 为 Redis) | | springdoc-openapi | 3.1.1 | Boot 4 系必须 v3 | | Apache Fesod | 2.0.2-incubating | Excel 导入导出(EasyExcel 的 Apache 继任者,坐标 `fesod-sheet`) | | AWS SDK for Java v2(S3) | 2.30.0 | `file` 模块 S3 通用存储模式 | | 前端 | Vue 3.5 / Element Plus 2.9 / Vite 6 / TS 5.8 / Pinia 2 | `mate-ui` | > **版本唯一真源**:`mate-dependencies/pom.xml`(独立 BOM,不继承根 POM)+ 根 `pom.xml` 的 `properties`。 > 业务模块 POM **禁止**出现任何三方版本号;内部兄弟模块统一 `${project.version}`。 --- ## 五、功能特性 ### 5.1 对外 REST 契约:保持 MateCloud `/api/v1/**` **关键决策(保证 `mate-ui` 零改动)**:单体直接暴露 MateCloud 原样的路径前缀,不做路径重写。 | 域 | 路径前缀 | 代表端点 | | --- | --- | --- | | 认证 | `/api/v1/auth` | ✅ `POST /login`、`POST /logout`;🔶 图片验证码 / 短信 / SSO / LDAP 登录、`GET /me`、`PUT /password`、`GET /sso/authorize`(T6.3/T6.4 规划) | | 用户 | `/api/v1/users` | `GET /`、`POST /`、`PUT /{id}`、`DELETE /{id}`、`GET /export`、`POST /import` | | 角色 | `/api/v1/admin/roles` | CRUD + 菜单/数据权限分配 | | 菜单 | `/api/v1/admin/menus` | 菜单树 CRUD、路由生成 | | 租户 | `/api/v1/admin/tenants` | CRUD、`GET /by-code/{code}`、套餐 | | 部门/岗位 | `/api/v1/admin/depts`、`/api/v1/admin/posts` | 树形 CRUD | | 字典/参数 | `/api/v1/admin/dict`、`/api/v1/admin/config` | 字典类型/数据、系统参数 | | 日志 | `/api/v1/admin/operation-logs`、`/api/v1/admin/login-logs` | 分页查询、详情 | | 在线用户 | `/api/v1/admin/online-users` | 列表、强制下线 | | 监控 | `/api/v1/admin/monitor` | `/dashboard`、`/server`、`/cache` | | 通知 | `/api/v1/notice` | ✅ 站内信 / 邮件 / 短信 / 推送四渠道 + SSE 订阅(`notice:send:*` 权限标识;路径以 docs/02 单数 `/api/v1/notice` 为准,复数别名归网关 rewrite) | | 文件 | `/api/v1/files` | ✅ 上传 / 下载 / 预签名 URL / 分片(LOCAL 本地磁盘 + 通用 S3 兼容对象存储:AWS S3 / 阿里云 OSS / 腾讯云 COS / MinIO / 华为云 OBS / 七牛 等,统一 AWS SDK for Java v2) | | AI | `/api/v1/ai` | ✅ `/chat`、`/chat/stream`(SSE);🔶 `/tools` 端点、MCP Server(`mate --mcp`,T6.3/T6.4 规划) | | 开放接口 | `/api/v1/open/**` | 🔶 `@ApiSign` HMAC-SHA256 验签(规划,尚未实现) | > 需求书示例中的 `/api/system/**`、`/api/auth/**` 仅作为**网关内部路由分组**使用;对外路径以本表为准。 > 状态图例:✅ 已实现(密码登录 / 通知四渠道 / 文件存储 / AI 对话)|🔶 规划中(T6.3/T6.4/T7.x 待交付):短信 / SSO / LDAP 登录、开放接口签名、限流 / 幂等 / 数据权限切面、事件外部化 AMQP。 ### 5.2 能力清单 | 能力域 | 功能 | 状态 | 实现要点 | | --- | --- | --- | --- | | 认证 | 密码登录 + 登出 | ✅ | Sa-Token;Token 校验下沉到各模块 `interfaces` 层拦截器 | | 认证 | 登录失败锁定、会话互斥 | ✅ | `mate.auth.login-lock.*`(max-attempts / lock-seconds);锁定复用平台码 `SECB003` | | 认证 | 短信 / SSO / LDAP 登录、验证码 | 🔶 | 复用 `LoginCommandService` 的锁定 / 审计 / 事件装配(T6.3 规划) | | RBAC | 用户-角色-菜单三级绑定、接口级鉴权 | ✅ | `@SaCheckPermission`,权限标识 `<模块>:<资源>:<动作>`;角色 / 权限解析落 auth 侧带缓存(空结果不写缓存) | | 多租户 | 租户 CRUD + 行级隔离 | ✅ | `TenantLineInnerInterceptor` 自动注入 `tenant_id`(varchar 层雪花);`X-Tenant-Id`;无上下文 **fail-closed** | | 多租户 | 隔离策略 SPI | 🔶 | 默认 `ROW`;`SCHEMA` / `DATASOURCE` 为预留扩展点(未实现) | | 审计 | 操作日志 / 登录日志 | ✅ | `@AuditLog` AOP 发布事件 → 异步落库,失败不影响主流程 | | 事件 | 领域事件 + 注册表状态机 | ✅ | `@ApplicationModuleListener`;`PUBLISHED→PROCESSING→COMPLETED/FAILED→RESUBMITTED` | | 事件 | 失败重发 / 归档 / 死信 | ✅ | `mate-starter-event` 三个运维任务 + `/actuator/events`、`/actuator/events-dead-letter` | | 事件 | 事件外部化 | 🔶 | `@Externalized` + AMQP/RabbitMQ(依赖与配置已占位,未启用;进程内事件禁止外部化) | | 横切 | 限流 / 幂等 / 签名 / 脱敏 / 数据权限 | 🔶 | `@RateLimit` / `@Idempotent` / `@ApiSign` / `@Desensitize` / `@DataPermission`(规划,尚未实现) | | 文件 | 上传 / 下载 / 预签名 / 分片 | ✅ | `FileStorageService` 命名接口,LOCAL 本地磁盘 + 通用 S3 兼容(AWS SDK v2):AWS S3 / 阿里云 OSS / 腾讯云 COS / MinIO / 华为云 OBS / 七牛 | | Excel | 导入 / 导出 | ✅ | Apache Fesod 封装(`@ExcelExport` / `@ExcelImport`);`ImportResult` 契约字段已钉死 | | 任务 | 幂等重入 + 执行历史 | ✅ | `mate-starter-job`(`mate_job_execution` 全局运维表,非租户表) | | AI | `@Tool` 自动发现、流式对话 | ✅ | `AiChatService` 命名接口;`domain` 零 Spring AI 依赖(契约测试钉死) | | AI | MCP Server(`mate --mcp`) | 🔶 | T6.4 规划 | | 架构 | 边界校验 + 领域纯净 | ✅ | `verify()` + ArchUnit `DomainPurityTest` | | 可观测 | 模块拓扑 / 事件注册表 / 指标 / 追踪 | ✅ | `/actuator/modulith`、`/actuator/events`、Prometheus、MDC 三键(`traceId`/`tenantId`/`userId`) | --- ## 六、模块说明 ``` mate-modulith/ ├── pom.xml # 根 POM:packaging=pom,parent=spring-boot-starter-parent:4.1.1 ├── mate-dependencies/ # 【BOM】独立 POM(无 parent):三方版本唯一真源 ├── mate-common/ # 【共享内核 · Modulith 模块 common · OPEN】 │ # Result/PageResult/PageQuery/BizException/ErrorCode/ │ # TenantContextHolder/CurrentUserPort/通用注解/枚举 ├── mate-starters/ # 【基础设施能力聚合】代码包 com.mate.common.* │ ├── mate-starter-web/ # ✅ 统一响应、全局异常出口、Jackson 3、OpenAPI、CORS、TraceId、 │ │ # MDC 三键、@AuditLog 切面 │ ├── mate-starter-datasource/ # ✅ MyBatis-Plus、租户行级(fail-closed)、审计填充、BaseEntity │ ├── mate-starter-security/ # ✅ Sa-Token 装配、Redis DAO 兼容层、注解鉴权拦截器 │ ├── mate-starter-cache/ # ✅ Caffeine L1 + Redis L2、分布式锁 │ ├── mate-starter-event/ # ✅ 事件注册表运维:重发 / 清理 / 死信归档 + Actuator 端点 │ ├── mate-starter-job/ # ✅ 任务模板(幂等重入)+ 执行历史(mate_job_execution) │ ├── mate-starter-mq/ # 🔶 占位骨架(事件外部化通道,T6.3 规划启用) │ ├── mate-starter-excel/ # ✅ Apache Fesod 封装(@ExcelExport / @ExcelImport) │ └── mate-starter-test/ # ✅ MateIntegrationTest / ModulithGuardTest / Testcontainers 基类 ├── mate-modules/ # 【业务能力 = Modulith 应用模块聚合】 │ ├── mate-module-auth/ # com.mate.auth 认证身份(密码登录/登出/锁定/权限解析) │ ├── mate-module-system/ # com.mate.system 系统管理(用户/角色/菜单/组织/字典/参数/租户/审计) │ │ └── rbac/ # com.mate.system.rbac 嵌套子模块(用户/角色/菜单聚合, │ │ # 契约实现 UserAccountApiImpl/UserPermissionApiImpl 归此) │ ├── mate-module-notice/ # com.mate.notice 通知(四渠道适配器 + SSE 推送) │ ├── mate-module-file/ # com.mate.file 文件存储(LOCAL 本地磁盘 + 通用 S3 兼容对象存储) │ └── mate-module-ai/ # com.mate.ai AI 对话(Spring AI 适配 + @Tool 发现) ├── mate-monolith/ # 【可执行启动模块】MateCloudApplication + application.yml │ # + Flyway 全局基线 db/migration/__root(事件注册表 DDL 等) │ # + MateCloudModulithTest(verify())+ Documenter ├── mate-gateway/ # 独立网关进程(WebFlux 轻量网关:路由转发 + 别名 rewrite + SSE 透传 + 治理端点,不做 Token 校验) ├── mate-cli/ # CLI + MCP Server(mate --mcp,spring-ai @McpTool 暴露 ai 能力) └── mate-ui/ # 【前端】Vue 3.5 + Element Plus + Vite 6 + TS + Pinia(仓库内复刻) ``` --- ## 七、关键架构决策台账(吸收三个参考项目的最佳设计) | # | 决策 | 来源 | 理由 | | --- | --- | --- | --- | | 1 | **独立 BOM**(`mate-dependencies` 不继承根 POM,根 POM `import` 它) | mate | 若 BOM 继承根 POM 且根 POM `import` 它,Maven 解析阶段即构成环(`Non-resolvable import POM`) | | 2 | **`@Modulithic(systemName, sharedModules="common")` + 启动类置于根包** | mate | 业务模块成为根包的直接子包,被 `direct-sub-packages` 策略识别(跨 jar 同样生效) | | 3 | **`type=CLOSED` 业务模块 + `OPEN` 共享内核**,`displayName` 用中文 | mate | 显式声明「谁能被谁依赖」;`verify()` 可强制校验 | | 4 | **`api` / `api/dto` / `api/event` 逐包声明 `@NamedInterface("api")`** | mate(实跑验证) | Modulith 命名接口**不递归包含子包**,只声明父包会漏掉契约 | | 5 | **模块感知 Flyway**:基路径 `classpath:db/migration` + `runtime.flyway-enabled=true` + `db/migration//` | mate | 模块自治演进、版本线不争用;测试可只跑相关模块迁移。yin 的全局单线版本号在多模块并行时冲突 | | 6 | **事件注册表 JDBC + DDL 固化进 Flyway**(`schema-initialization.enabled=false`) | mate | 建表可控、可审计、可回滚;避免运行期隐式建表 | | 7 | **事件注册表 v2 状态机显式声明** `use-legacy-structure=false` | Spring Modulith 2.x 官方 | 启用 `STATUS / COMPLETION_ATTEMPTS / LAST_RESUBMISSION_DATE` 三列,才能做重发与死信运维 | | 8 | **事件注册表运维三件套**:重发 / 清理 / 死信归档 + Actuator 端点 | mate + yin | `completion-mode=update` 下完成记录会累积,需主动清理;失败事件需可观测可重投 | | 9 | **事件外部化(`@Externalized` + AMQP + Jackson 3)** | 需求书(mate/yin 均未实现) | 真正落 outbox 语义:进程内走监听器,需跨进程的事件投递到 MQ | | 10 | **契约物理隔离的取舍**:契约放各模块 `api/` 包,而非独立 `-api` jar | mate(vs yin) | 对 5 个业务模块规模,`api/` 包 + `verify()` + ArchUnit 已足够;独立 jar 的编译期强隔离留待拆分微服务时启用 | | 11 | **`domain` 包框架零依赖 + ArchUnit 守护** | yin(`DomainPurityTest`) | 需求书明令禁止 `domain` 出现 `@Service`/`@Component`;用测试而非口头约定强制 | | 12 | **租户无上下文 fail-closed + 绕过必留痕 + `supplyWithIgnore`** | yin | 静默放行是租户隔离最危险的失效模式 | | 13 | **Sa-Token Redis DAO 兼容层** | yin(`SaTokenDaoCompatConfig`) | Sa-Token 默认 Redis DAO 依赖 Redis 6+ `KEEPTTL`;且避免引入 Jackson 2(与 Boot 4 的 Jackson 3 冲突) | | 14 | **对外路径保持 `/api/v1/**`** | matecloud | `mate-ui` 零改动对接(其 `baseURL=/api/v1`,nginx 保留前缀) | | 15 | **Token 校验下沉到模块 `interfaces` 层,网关只管路由与限流** | 需求书 | 单体形态下网关不是安全边界;避免「网关信任」反模式 | | 16 | **`system` 单模块承载 5 个聚合**(用户/角色/菜单/字典/参数) | 需求书(vs mate 的 9 模块细分) | 契约路径本就是 `/api/v1/admin/**` 同域;已用 Modulith **嵌套子模块** `com.mate.system.rbac` 承载用户/角色/菜单聚合(父↔子互相放行,契约实现 UserAccountApiImpl/UserPermissionApiImpl 归子模块,避免父↔子 slice 环),其余细分留待拆分微服务 | | 17 | **不用 Lombok**,DTO/VO/事件统一 `record` | mate | JDK 25 下 Lombok 注解处理链存在兼容风险;`record` + 显式代码可读性与注释质量更高 | | 18 | **`/actuator/modulith` 只暴露模块拓扑,事件状态另设 `/actuator/events`** | 官方文档 + mate/yin | 官方 `spring-modulith-actuator` 不暴露事件注册表,需求书预期的"拓扑 + 事件状态"需两个端点合力 | --- ## 八、配置说明 全部配置集中在 `mate-monolith/src/main/resources/application.yml`(无 Nacos,配置走 Spring Boot 4 `ConfigData`:本地 yml + 环境变量 + profile 覆盖)。 | 配置项 | 说明 | | --- | --- | | `server.port` | 后端端口,默认 `8080`(联调惯例 `18080`) | | `management.server.port` | 管理端口(**未单独设置,默认与 `server.port` 同端口**;生产建议独立端口并加鉴权,T4.2 拦截器上线前勿暴露公网) | | `spring.datasource.*` | MySQL + HikariCP | | `spring.flyway.locations` | **固定写基路径 `classpath:db/migration`**;错写子路径会被 Modulith 追加为 `__root/__root`,静默不建表 | | `spring.modulith.detection-strategy` | `direct-sub-packages` | | `spring.modulith.runtime.flyway-enabled` | `true`:启用模块感知迁移 | | `spring.modulith.runtime.verification-enabled` | `true`:启动期校验模块结构 | | `spring.modulith.events.completion-mode` | `update`(保留完成记录,由 `mate-starter-event` 定期清理) | | `spring.modulith.events.jdbc.use-legacy-structure` | `false`:启用 v2 状态机结构(`STATUS` / `COMPLETION_ATTEMPTS` / `LAST_RESUBMISSION_DATE`) | | `spring.modulith.events.jdbc.schema-initialization.enabled` | `false`:DDL 由 Flyway `__root` 固化,禁止隐式建表 | | `spring.modulith.events.republish-outstanding-events-on-restart` | `false`(多副本防重复投递;重发属运维显式动作) | | `spring.modulith.events.staleness.*` | 陈旧阈值:`published` / `processing` / `resubmitted`,超时由监视器标记 `FAILED` | | `spring.modulith.events.externalization.*` | **占位未启用**(T6.3 规划);进程内事件禁止外部化 | | `spring.jackson.*` | Jackson 3 全局行为;**禁止**写 `write-dates-as-timestamps`(该键已移除,绑定即启动失败) | | `mybatis-plus.*` | 雪花主键、逻辑删除、驼峰映射 | | `sa-token.*` | `token-name: Authorization`、有效期、并发登录策略 | | `mate.tenant.ignore-tables` | 租户行级隔离白名单(框架表 + 无 `tenant_id` 的全局业务表 + `mate_job_execution` 运维表);支持 `前缀*` 通配 | | `mate.ai.fake` | `true`=确定性假模型驱动全链路(无 Provider Key 环境);**生产必须显式置 `false`** | | `mate.ai.chat.memory-window` | 会话记忆窗口(每次对话注入最近 N 条历史,默认 20) | | `mate.ai.key-plain-fallback` | `true`=Provider Key 密文按明文透传(仅开发);生产前置:置 `false` + 落 AES-GCM 解密器(fail-closed 抛 `AIA018`) | | `mate.*` | 其余业务开关:`file.storage-type`、`notice.provider`、`mq.enabled`(占位)、`api-sign.*`、`rate-limit.*`(规划) | `application-prod.yml` 采用 **strict 占位符**:数据库口令、AES 密钥等**不设默认值**,未注入即启动失败。 --- ## 九、测试与验收 | 层次 | 手段 | 覆盖 | | --- | --- | --- | | 架构守护 | `MateCloudModulithTest`:`ApplicationModules.of(MateCloudApplication.class).verify()` + `Documenter` PlantUML | 模块无环、封装未破坏、`allowedDependencies` 未被绕过 | | 领域纯净 | ArchUnit `DomainPurityTest` | `domain` 包不得出现 Spring/Jakarta/MyBatis 注解;`domain` 不得依赖 `application`/`infrastructure` | | 模块切片 | `@ApplicationModuleTest`(`mate-starter-test` 的 `ModulithGuardTest` 基类) | 单模块领域逻辑 + 依赖边界 | | 事件链路 | `Scenario` + `PublishedEvents` / `AssertablePublishedEvents` | 发布 → 消费 → 状态变更全链路,含超时等待 | | 集成 | Testcontainers(MySQL 5.7/8.0 + Redis)+ `@DynamicPropertySource` | 模块特定 Flyway 迁移顺序、租户行隔离、认证链路 | ```bash mvn clean install # 含 verify() 边界校验,不绿不得交付 mvn test -pl mate-modules/mate-module-system mvn verify # 集成测试(Docker 必需) ``` **验收口径**(对应需求书第七节): 1. `mate-ui` 零改动对接:`/api/v1/**` 路径与 `Result` 响应体逐一对齐; 2. `ApplicationModules.verify()` 通过,无边界违规; 3. 跨模块通信 100% 走领域事件或 `::api` 命名接口; 4. `java -jar mate-monolith.jar` 单进程启动,不依赖 Nacos / Dubbo / RabbitMQ; 5. 每个模块有 `@ApplicationModuleTest` 覆盖核心领域逻辑与事件流; 6. 每个模块有独立 Flyway 迁移目录,启动按模块依赖顺序执行; 7. `/actuator/modulith` 返回正确模块拓扑,`/actuator/events` 返回事件注册表状态。 --- ## 十、与 MateCloud / mate / yin 的差异 | 维度 | MateCloud(微服务) | 本项目(模块化单体) | | --- | --- | --- | | 架构形态 | Spring Cloud + Dubbo 双形态 | 仅模块化单体,模块边界即拆分线 | | 注册 / 配置中心 | Nacos | **移除**,本地 yml + 环境变量(`ConfigData`) | | 服务间通信 | Dubbo RPC + MQ | `::api` 命名接口(同步)+ 领域事件(异步) | | 网关 | Spring Cloud Gateway + Nacos 发现 | 可选独立进程,静态编程式路由,不做鉴权 | | 事务性发件箱 | MQ 事务消息 | Spring Modulith Event Publication Registry(JDBC v2 状态机) | | 事件跨进程 | MQ 直接投递 | `@Externalized` 外部化(AMQP),进程内直接消费 | | 模块边界表达 | Maven 模块 + RPC 接口 | Maven 模块 + `@ApplicationModule` / `@NamedInterface`,可 `verify()` | | 代码组织 | 每服务一套 DDD 四层 | 每模块一套 DDD 四层,`domain` 强制框架无关 | | 数据库迁移 | 每服务独立版本线 | 模块感知 Flyway,按模块依赖顺序执行 | | 限流 / 灰度 / 分布式事务 / 分库分表 | Sentinel / Gray / Seata / ShardingSphere | 单体形态不引入(网关可选限流) | **明确禁止**(违反即返工):模块间直接注入对方 Repository / Mapper;保留任何 Nacos / Dubbo / Feign 依赖;把共享内核当垃圾桶;`domain` 包引入 Spring 注解。 --- ## 十一、实施路线图 | 阶段 | 内容 | 状态 | | --- | --- | --- | | 阶段零 | 工程治理:`README.md`、`AGENTS.md`、`.codebuddy/rules/`、`.gitignore` | ✅ 完成 | | 阶段一 | 项目骨架:`mate-dependencies` BOM、根 POM、`mate-monolith` 启动模块、`package-info.java`、启动期结构校验 | ✅ 完成 | | 阶段二 | 领域模型提取:`system` 五聚合入 `domain`,`mate-common` 拆分共享内核 / 模块内模型,定义 Named Interface | ✅ 完成 | | 阶段三 | 事件驱动改造:RPC → 领域事件,注册表 JDBC + v2 状态机,模块特定 Flyway 迁移 | ✅ 完成 | | 阶段四 | 认证与安全:Sa-Token 下沉到模块 `interfaces`、密码登录/登出/锁定、权限解析、三段式授权、租户行级隔离、网关编程式路由 | ✅ 完成 | | 阶段五 | 基础设施适配:移除 Nacos/Dubbo、MQ 仅作外部化(占位)、`file` 模块(LOCAL + 通用 S3 兼容存储)、`notice` 四渠道、`mate-starter-job`+`mate-starter-excel`、Actuator + Prometheus | ✅ 完成 | | 阶段六 | Spring AI:`ai` 模块 + `AiChatService` 命名接口 + 流式对话 + `@Tool` 发现 + `mate --mcp`(CLI/MCP) | 🔶 核心切片完成(T6.1/T6.2);AI 端点(T6.3)、CLI/MCP(T6.4)待交付 | | 阶段七 | 验证与测试:`@ApplicationModuleTest`、架构守护、Testcontainers、前后端联调 | 🔶 待派发(T7.1/T7.2/T7.3) | --- ## 十二、Agent / 编码约定入口 | 文件 | 作用 | | --- | --- | | [AGENTS.md](AGENTS.md) | Agent 进入仓库的第一阅读入口:项目速览、常用命令、目录导航、硬性红线、验收口径 | | [.codebuddy/rules/](.codebuddy/rules/) | CodeBuddy 项目规则(`.codebuddy/rules/<规则名>/RULE.mdc`):`modulith-boundaries` 全程 Always 生效,其余按相关性自动加载 | 二者分工:`AGENTS.md` 管「怎么在这个仓库里干活」,`.codebuddy/rules/` 管「改到哪类文件必须遵守哪些硬约束」。 --- ## 十三、开源协议 本项目基于 [MIT License](LICENSE) 开源。 业务蓝本 [MateCloud](https://gitee.com/matevip/matecloud) 为 Apache 2.0 协议,致敬其设计理念:**最小公共、各司其职、Starter = 即插即用能力**。