|
|
|
|
@ -0,0 +1,143 @@
|
|
|
|
|
# 数字人民币教学仿真后端开发规范
|
|
|
|
|
|
|
|
|
|
本文档是本项目新增模块、接口和数据表时的统一约定。目标是在业务持续扩展时保持领域边界清晰、认证安全、数据可演进。
|
|
|
|
|
|
|
|
|
|
## 1. 架构总览
|
|
|
|
|
|
|
|
|
|
项目采用 DDD 的“按限界上下文分包”方式。一个顶层模块代表一个业务能力,而不是一个技术层。
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
flowchart LR
|
|
|
|
|
Client[前端 / 调用方] --> API[interfaces 接口层]
|
|
|
|
|
API --> App[application 应用层]
|
|
|
|
|
App --> Domain[domain 领域层]
|
|
|
|
|
App --> Infra[infrastructure 基础设施层]
|
|
|
|
|
Infra --> DB[(本系统 MySQL)]
|
|
|
|
|
PI[platformintegration 防腐层] --> Platform[(主平台 / CAS)]
|
|
|
|
|
API --> Security[security 认证上下文]
|
|
|
|
|
Security --> DB
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
当前限界上下文如下:
|
|
|
|
|
|
|
|
|
|
| 模块 | 职责 | 禁止承担的职责 |
|
|
|
|
|
| --- | --- | --- |
|
|
|
|
|
| `issuance` | 数字人民币发行相关业务域;当前仅有领域 ID 示例 | 用户认证、主平台 Token 解析 |
|
|
|
|
|
| `identity` | 教师/学生身份快照、角色投影与同步 | 提供用户、角色 CRUD |
|
|
|
|
|
| `security` | 本系统 JWT、登录、会话兑换、刷新令牌与退出 | 业务领域规则、主平台协议解析 |
|
|
|
|
|
| `platformintegration` | 主平台 Token、CAS 和主平台只读查询的防腐适配 | 业务数据落库、业务接口 |
|
|
|
|
|
| `shared` | 仅放跨模块通用能力:响应体、异常、审计、基础配置 | 具体业务实体、业务 Service |
|
|
|
|
|
|
|
|
|
|
## 2. 新模块必须新建顶层文件夹
|
|
|
|
|
|
|
|
|
|
新增一个独立业务能力时,必须在 `src/main/java/com/yau/digitalrmb/` 下创建新的顶层模块目录。例如钱包、账单或课程场景应分别创建:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
wallet/
|
|
|
|
|
ledger/
|
|
|
|
|
course/
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
不要把新业务类直接放入 `shared`、`security`、`identity` 或根包。只有确实属于这些既有上下文的功能,才允许扩展其目录。
|
|
|
|
|
|
|
|
|
|
每个新模块默认使用以下目录结构;没有内容的目录不要提前创建:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
<module>/
|
|
|
|
|
├── domain/
|
|
|
|
|
│ ├── model/ # 聚合、实体、值对象、枚举、领域事件
|
|
|
|
|
│ ├── service/ # 无法归属单个聚合的纯领域服务
|
|
|
|
|
│ └── repository/ # 仓储接口(端口),不含 MyBatis 实现
|
|
|
|
|
├── application/
|
|
|
|
|
│ ├── command/ # 写操作命令及处理器
|
|
|
|
|
│ ├── query/ # 查询模型与查询服务
|
|
|
|
|
│ └── service/ # 用例编排、事务边界
|
|
|
|
|
├── infrastructure/
|
|
|
|
|
│ ├── persistence/
|
|
|
|
|
│ │ ├── entity/ # MyBatis-Plus 持久化实体
|
|
|
|
|
│ │ ├── mapper/ # Mapper 接口与 XML(如需要)
|
|
|
|
|
│ │ └── repository/ # 仓储接口的实现
|
|
|
|
|
│ └── client/ # 外部 HTTP、消息或文件系统适配器
|
|
|
|
|
└── interfaces/
|
|
|
|
|
├── rest/ # Controller
|
|
|
|
|
└── dto/ # 请求/响应 DTO
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
简单只读查询可以不创建完整聚合,但 Controller 仍不得直接调用 Mapper;应由 `application.query` 中的查询服务负责。
|
|
|
|
|
|
|
|
|
|
## 3. 分层与依赖方向
|
|
|
|
|
|
|
|
|
|
依赖只允许由外向内:
|
|
|
|
|
|
|
|
|
|
```text
|
|
|
|
|
interfaces → application → domain
|
|
|
|
|
infrastructure → domain / application 定义的端口
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
具体规则:
|
|
|
|
|
|
|
|
|
|
- `domain` 不依赖 Spring、MyBatis-Plus、Controller、数据库实体或 HTTP DTO。
|
|
|
|
|
- `application` 负责一个用例的编排、权限检查和事务边界;不编写 SQL,不返回 MyBatis 实体。
|
|
|
|
|
- `infrastructure` 实现数据库和外部系统适配;Mapper 只能被本模块的仓储实现或查询服务使用。
|
|
|
|
|
- `interfaces` 只负责参数校验、调用应用服务、转换 DTO;不得包含业务规则。
|
|
|
|
|
- 跨模块访问优先通过对方暴露的应用服务、领域事件或端口;禁止直接引用对方的 Mapper/Entity。
|
|
|
|
|
- `shared` 仅接收至少两个模块真实复用且不携带业务语义的代码。不要把“暂时不知道放哪里”的类放入 `shared`。
|
|
|
|
|
|
|
|
|
|
## 4. 领域建模规则
|
|
|
|
|
|
|
|
|
|
- 每个写模型先确定聚合根和不变量;一次事务只修改一个聚合。
|
|
|
|
|
- 用值对象表达金额、账户号、申请编号、状态等有业务含义的概念,避免在 Service 中散落 `String`、`BigDecimal` 和状态码。
|
|
|
|
|
- 聚合 ID 使用独立类型,例如现有的 `IssuanceApplicationId`;接口层和持久化层再做转换。
|
|
|
|
|
- 状态流转由聚合方法表达,例如 `approve()`、`reject()`;不要在 Controller 或 Mapper 中直接改状态字段。
|
|
|
|
|
- 需要跨聚合通知时发布 `shared.domain.DomainEvent`,由应用层或基础设施层处理副作用。
|
|
|
|
|
|
|
|
|
|
## 5. 数据库与 Flyway 规范
|
|
|
|
|
|
|
|
|
|
- 所有表结构和内置数据变化必须新增 `src/main/resources/db/migration/V<版本>__<英文描述>.sql`。
|
|
|
|
|
- 已发布的迁移文件不得修改、删除或重命名;修复必须创建新版本迁移。
|
|
|
|
|
- 表名、字段名使用 `snake_case`;Java 字段使用 `camelCase`,通过 MyBatis-Plus 显式映射差异字段。
|
|
|
|
|
- 新业务表必须有主键、必要索引,以及 `created_at`、`updated_at`、`created_by`、`updated_by`、`deleted` 审计字段;可继承 `AuditableEntity`。
|
|
|
|
|
- 金额使用 `DECIMAL`,禁止使用 `float`/`double`;时间使用 `TIMESTAMP`,统一以 UTC 语义处理。
|
|
|
|
|
- 身份、角色和用户角色仅能由内部投影或迁移写入;不得新增对外 CRUD 接口。
|
|
|
|
|
- 禁止将密码、Token、验证码或敏感凭据写入业务表、日志、迁移文件或测试快照。
|
|
|
|
|
|
|
|
|
|
## 6. API 与异常规范
|
|
|
|
|
|
|
|
|
|
- REST Controller 放在 `<module>.interfaces.rest`,路径统一以 `/api/v1/` 开头。
|
|
|
|
|
- 请求 DTO 使用 `jakarta.validation` 注解;Controller 参数标注 `@Valid`。
|
|
|
|
|
- 对外成功响应统一使用 `ApiResponse<T>`,不要自行定义不一致的响应包装格式。
|
|
|
|
|
- 可预期业务错误抛出 `BusinessException` 并使用 `ErrorCode`;不要在 Controller 中 `try/catch` 后吞掉异常。
|
|
|
|
|
- 接口响应只返回 DTO,不返回 MyBatis Entity、密码哈希、刷新令牌摘要或主平台 Token。
|
|
|
|
|
- 新接口需补充 Springdoc 注解与说明,确保 Swagger 可读;不在 Swagger 暴露用户、角色或用户角色管理接口。
|
|
|
|
|
|
|
|
|
|
## 7. 认证与权限规范
|
|
|
|
|
|
|
|
|
|
- 所有新业务接口默认需要本系统 JWT;只有登录、CAS 回调和必要健康检查可以匿名。
|
|
|
|
|
- 当前用户从 Spring Security 的 `Jwt`/`Authentication` 获取,业务模块不得解析主平台 Token。
|
|
|
|
|
- 角色只允许 `TEACHER`、`STUDENT`;权限判断放在应用层或 Spring Security 配置中,不能由前端传入角色决定。
|
|
|
|
|
- `platformintegration` 是唯一可以处理主平台 Token、CAS Ticket 和主平台只读数据源的模块。
|
|
|
|
|
- 主平台连接只授予 `SELECT`;本系统 MySQL 使用主数据源,主平台只读数据源不得被 Flyway 或业务写操作复用。
|
|
|
|
|
|
|
|
|
|
## 8. 测试与提交规范
|
|
|
|
|
|
|
|
|
|
- 新领域规则写单元测试;新增接口至少写 `MockMvc` 集成测试;新增迁移需覆盖启动迁移和关键读写。
|
|
|
|
|
- 修复缺陷先增加可复现的失败测试,再实现修复。
|
|
|
|
|
- 提交前至少运行:
|
|
|
|
|
|
|
|
|
|
```powershell
|
|
|
|
|
mvn test -DforkCount=0 -B
|
|
|
|
|
mvn package -DskipTests -B
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
- 提交信息采用 `<type>: <英文简述>`,例如 `feat: add wallet transfer aggregate`、`fix: prevent duplicate issuance`、`docs: add module development guide`。
|
|
|
|
|
- 一个提交只做一类明确变更;不要混入格式化、无关重构或本地配置文件。
|
|
|
|
|
|
|
|
|
|
## 9. 新模块自检清单
|
|
|
|
|
|
|
|
|
|
- [ ] 已创建新的顶层模块目录,而非把业务代码放入 `shared`。
|
|
|
|
|
- [ ] 已区分 `domain`、`application`、`infrastructure`、`interfaces` 职责。
|
|
|
|
|
- [ ] Controller 未直接调用 Mapper,且未返回持久化实体。
|
|
|
|
|
- [ ] 新增数据库变化使用新的 Flyway 版本迁移。
|
|
|
|
|
- [ ] 接口已校验参数、统一响应,并补充 Swagger 说明。
|
|
|
|
|
- [ ] 未记录或返回密码、Token、验证码等敏感信息。
|
|
|
|
|
- [ ] 已补齐单元/集成测试并通过 Maven 验证。
|