WholeProcessPlatform/backend/docs/业务模块开发技术规范.md
2026-05-21 11:35:09 +08:00

580 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# WholeProcessPlatform Backend 业务模块开发技术规范
## 1. 文档目的
本文档用于统一 `d:\shuili\WholeProcessPlatform\backend` 项目中业务模块的开发方式,重点覆盖:
- 模块目录与分层设计规范
- Controller、Service、Mapper、VO、Domain 的职责边界
- 基于 `Spring Boot 4.0.3 + Java 21 + MyBatis/MyBatis-Plus` 的编码约束
- 当前项目已形成的事实标准
- 新增业务模块、旧系统迁移模块、字典/基础数据模块的推荐实现方式
- SQL、异常、接口返回、分页、文档、测试、性能与安全要求
本文档适用于本项目所有新增或改造的业务模块,尤其适用于 `env` 目录下的生态环境类业务。
## 2. 技术基线
根据项目当前 `pom.xml`,本项目业务开发技术基线如下:
- JDK21
- Spring Boot4.0.3
- Spring WebMVC
- Spring Security已引入
- Springdoc OpenAPI3.0.2
- MyBatis3.5.16
- MyBatis Spring Boot Starter4.0.1
- MyBatis-Plus3.5.16,使用 `mybatis-plus-spring-boot4-starter`
- 数据库驱动MySQL、Oracle、达梦
- 工具库Hutool、Lombok、Guava、POI
## 3. 外部参考原则
本文档参考了当前主流的 Spring Boot 4 / 现代 Spring 开发建议,并结合项目现状做了落地约束,核心依据如下:
- Spring Boot 官方文档强调代码结构、配置类组织、依赖注入、外部化配置、日志、Web、Data、Validation、Actuator 等能力应作为应用开发基础。
- Springdoc 官方文档建议使用 `springdoc-openapi-starter-webmvc-ui` 作为 OpenAPI/Swagger UI 集成方式,并通过注解与配置文件维持接口文档。
- MyBatis Spring Boot Starter 官方文档强调在 Boot 4 体系中使用官方 starter、自动扫描 Mapper、使用配置项统一管理 MyBatis 行为。
- MyBatis-Plus 官方文档明确支持 Spring Boot 4推荐使用 Boot 4 对应 starter并采用 `BaseMapper`、`ServiceImpl`、分页对象等标准方式实现常规 CRUD。
说明:
- 本规范不是照搬互联网通用模板,而是“以本项目实际代码为准,吸收外部最佳实践后形成的可执行规范”。
- 若通用建议与现有项目框架存在冲突,优先保证现有项目兼容性,再逐步演进。
## 4. 当前项目模块结构总结
`env` 模块已经形成两类主流实现风格。
### 4.1 基础资料型模块
典型文件:
- `controller/SdCountryBController.java`
- `service/ISdCountryBService.java`
- `service/impl/SdCountryBServiceImpl.java`
- `mapper/SdCountryBMapper.java`
- `domain/SdCountryB.java`
特征:
- 面向单表或轻量多表的增删改查
- Service 通常继承 `ServiceImpl<Mapper, Domain>`
- 使用 `BaseMapper` 和 MyBatis-Plus `lambdaQuery()`
- Controller 以分页查询、列表查询、详情查询为主
适用场景:
- 字典表
- 基础资料表
- 标准后台管理页面
### 4.2 业务查询/迁移型模块
典型文件:
- `controller/SdWTMonitorController.java`
- `service/SdWtMonitorService.java`
- `service/impl/SdWtMonitorServiceImpl.java`
- `service/AlongListService.java`
- `service/impl/AlongListServiceImpl.java`
- `mapper/AlongDetailMapper.java`
- `mapper/SdWtMonitorMapper.java`
- `entity/vo/*`
特征:
- 来自旧系统迁移的复杂业务查询较多
- Controller 聚合多个业务接口
- Service 接口与实现手写,通常不继承 `ServiceImpl`
- 同时存在注解 SQL、动态 SQL、MyBatis-Plus 分页
- 使用 `DataSourceRequest`、`DataSourceResult` 适配旧平台 Kendo/DevExtreme 风格
适用场景:
- 旧系统模块迁移
- 复杂统计、图表、对比分析、联表明细
- 需要兼容旧平台入参与返回结构的接口
## 5. 模块分层规范
### 5.1 Controller 层职责
Controller 仅负责:
- 暴露路由
- 参数接收
- 基础空值校验
- 调用 Service
- 统一包装 `ResponseResult`
Controller 禁止:
- 拼接 SQL
- 大段业务判断
- 循环组装复杂结果
- 直接操作 Mapper
当前项目推荐写法:
- 类上使用 `@RestController`
- 类上使用 `@RequestMapping`
- 类上使用 `@Tag`
- 方法上使用 `@Operation`
- 返回值统一为 `ResponseResult`
示例风格:
- 业务聚合 Controller`SdWTMonitorController`
- 管理型 Controller`SdCountryBController`
### 5.2 Service 层职责
Service 层负责:
- 业务编排
- 参数解析
- 分页对象生成
- 调用 Mapper
- Java 层补充计算
- 返回对象组装
Service 层应根据模块类型选择实现方式:
- 基础 CRUD优先 `IxxxService + ServiceImpl`
- 复杂业务查询:优先 `XxxService + XxxServiceImpl`
- 旧系统迁移模块:优先显式定义业务接口,避免泛化成通用 CRUD Service
### 5.3 Mapper 层职责
Mapper 层负责:
- 数据查询与数据写入
- 注解 SQL 或 XML SQL
- 复杂 join、exists、聚合、分页 SQL
Mapper 层禁止:
- 放业务语义不清的万能 SQL
- 将参数语义不明确地混在同一个方法中
- 为了省事直接将前端字段名等同于数据库字段名而不做映射说明
### 5.4 VO / DTO / Domain 职责
当前项目已存在三类对象:
- `domain`:数据库实体,主要服务于 MyBatis-Plus CRUD
- `entity/vo`:前端返回对象、业务查询对象
- `common`:分页、过滤、排序、结果包装对象
规范要求:
- 单表管理页优先使用 `domain`
- 复杂查询、聚合结果、旧接口兼容结构必须使用独立 VO
- 不允许复用 `domain` 直接承接复杂联表查询结果
- 前端字段名与数据库字段名不一致时SQL 必须用旧字段名作为别名返回
## 6. 推荐目录规范
新增业务模块建议按如下目录落位:
```text
src/main/java/com/yfd/platform/<module>/
controller/
service/
service/impl/
mapper/
domain/
entity/vo/
```
命名建议:
- Controller`XxxController`
- Service`XxxService`
- ServiceImpl`XxxServiceImpl`
- Mapper`XxxMapper`
- 管理类 Service`IXxxService`
- 管理类 ServiceImpl`XxxServiceImpl extends ServiceImpl`
- Domain与表/业务实体对应
- VO以业务含义命名`SdYearListVO`、`WtFishVo`
## 7. 接口设计规范
### 7.1 返回结构规范
本项目统一返回对象为 `ResponseResult`,必须使用:
- `ResponseResult.success()`
- `ResponseResult.successData(data)`
- `ResponseResult.error(msg)`
禁止:
- Controller 直接返回裸对象
- 不同模块返回结构不一致
- 同类接口同时混用 `Map`、实体、裸数组作为顶层响应
### 7.2 异常规范
业务异常统一使用 `BizException`
适用场景:
- 必填参数缺失
- 业务前置条件不满足
- 站点、工程、字典等基础数据不存在
- 旧接口兼容校验失败
推荐写法:
```java
if (StrUtil.isBlank(stcd)) {
throw new BizException("站点编码不能为空.");
}
```
禁止:
- `throw new RuntimeException(...)`
- Controller 静默吞异常
- Service 返回 `null` 表示明确错误
### 7.3 参数接收规范
当前项目主要有两类接口:
- Kendo/DevExtreme 风格:`@RequestBody DataSourceRequest`
- 标准后台管理风格:`@RequestParam` + 分页参数
规范要求:
- 旧平台迁移接口优先保留 `DataSourceRequest`
- 后台管理接口优先使用显式参数
- 不允许将大量业务字段塞入 `Map<String, Object>` 作为常规入参
- `Map<String, Object>` 仅用于动态字段更新、非结构化补丁写入等少数场景
## 8. 分页与筛选规范
### 8.1 `DataSourceRequest` 适用范围
`DataSourceRequest` 是本项目重要的兼容层对象,适用于:
- 迁移旧平台 Kendo Grid 接口
- 需要复杂 filter/group/sort/select 的业务页面
- 旧接口需要兼容前端请求结构时
规范要求:
- 迁移旧接口时优先从 `DataSourceRequest` 中提取明确字段
- 尽量封装公共提取逻辑,如使用 `QgcQueryWrapperUtil.getFilterFieldValue(...)`
- 对必要参数要先做空值校验
### 8.2 `DataSourceResult` 规范
使用 `DataSourceResult` 时应设置:
- `data`
- `total`
- `aggregates`
推荐:
- 无聚合时设置空 `HashMap<>`
- 无数据时返回空列表而不是 `null`
## 9. 依赖注入规范
现状:
- 项目中大量使用 `@Resource` 字段注入
建议:
- 存量代码允许继续使用 `@Resource`
- 新增业务模块优先使用构造器注入
- 若为了保持模块风格一致,可在同一文件中延续现有注入方式
统一要求:
- 不允许通过 `SpringContextHolder` 主动取 Bean 代替正常依赖注入,除非是历史兼容场景且无法重构
## 10. SQL 与数据访问规范
### 10.1 选型原则
优先级如下:
1. 单表 CRUD、简单条件分页MyBatis-Plus
2. 明确的小型查询Mapper 注解 SQL
3. 复杂迁移查询、动态列、旧 SQL 兼容:`MicroservicDynamicSQLMapper`
4. 复杂 XML 已有现成资产且迁移成本高:可保留 XML
### 10.2 MyBatis-Plus 适用规范
适用于:
- 基础字典
- 台账管理
- 后台标准分页列表
要求:
- 使用 `lambdaQuery()`、`lambdaUpdate()`
- 条件判断写在链式条件中
- 避免大量手写 SQL 替代简单 CRUD
### 10.3 动态 SQL 适用规范
当前项目已有 `MicroservicDynamicSQLMapper`,适用于:
- 旧系统 SQL 平移
- 表结构拆分后的复杂重写
- 返回 VO 列较多且结构动态
使用规范:
- 动态 SQL 必须先在 Service 中拼装完整语义,不允许把参数语义留给前端猜测
- SQL 返回字段必须使用 VO 字段名别名
- 参数统一通过 `Map<String, Object>` 绑定,禁止字符串直接拼接用户输入
- 非必要不要在 Service 中写多个层层嵌套的查询,优先压缩为可维护的单条 SQL 或小规模明确查询
### 10.4 SQL 编写要求
必须遵循:
- 过滤条件尽量前置
- 明确 `IS_DELETED = 0`
- 与旧系统兼容时保留 `USFL`、`MWAY`、`DTIN_TYPE`、`STTP` 等业务条件
- 联表字段语义必须先确认再关联
- 能用 `EXISTS` 的场景优先评估是否优于无谓 join
- 排序字段应稳定,避免前端列表顺序漂移
禁止:
- 用错误语义字段强行 join
- 在 SQL 中随意猜测旧字段映射
- 使用无法参数化的用户输入拼接 SQL
### 10.5 旧系统迁移专项规则
迁移模块时必须先做三件事:
1. 找到旧 Controller/Service/Mapper/XML 主入口
2. 梳理旧表关系和字段语义
3. 建立旧表到新表的映射说明
禁止:
- 未分析旧 SQL 语义就直接按字段名猜测重写
- 把旧“横表字段”误当成新“关系表字段”
- 为了快速实现,破坏旧接口请求和返回结构
## 11. 业务模块编码规范
### 11.1 Controller 编码规范
- 一个 Controller 只承载同一业务域或同一前端页面聚合能力
- 聚合型 Controller 可以包含多个子接口,但应保持前缀一致
- 方法名与 `@Operation(summary = "...")` 应表达真实业务语义
- 空值校验放在 Controller 或 Service 入口,不能完全依赖底层报错
### 11.2 Service 编码规范
- 一个方法只表达一个明确业务能力
- 复杂逻辑可拆为少量私有方法,但不要抽象出与旧业务语义脱节的“工具方法泛滥”
- 允许在 Service 层做二次排序、月份格式化、标志位组装、列头组装等 Java 后处理
- 数据库语义判断优先放 SQL纯展示逻辑优先放 Java
### 11.3 VO 编码规范
- VO 字段必须服务于前端返回,不要无意义堆字段
- 对旧接口兼容字段要保持命名稳定
- 使用 Lombok 时优先 `@Data``@Getter/@Setter`
- 对外 VO 建议加 `@Schema` 注释
### 11.4 Domain 编码规范
- Domain 应与真实表结构对齐
- 建议保持字段名、注释、表映射一致
- 不要将 VO 字段、临时业务字段塞进 Domain
## 12. 文档与 OpenAPI 规范
项目当前已引入 `springdoc-openapi-starter-webmvc-ui`,因此新增接口必须同时维护接口文档。
要求:
- Controller 类使用 `@Tag`
- 方法使用 `@Operation`
- 复杂 VO 使用 `@Schema`
- 对外接口要有清晰的 `summary`
推荐:
- 对关键参数补充 `description`
- 对复杂返回结构单独定义 VO不返回匿名 `Map`
- 将生产环境的 OpenAPI/Swagger UI 访问权限纳入安全控制
## 13. 配置管理规范
根据 Spring Boot 官方建议,配置应外部化管理。
项目要求:
- 数据源、缓存、安全、文档开关、日志级别等必须放配置文件
- 多环境配置使用 profile 管理
- 不允许将数据库地址、账号、密码、第三方密钥硬编码进 Java 代码
- 与数据库方言相关的行为尽量通过配置或基础层封装统一管理
## 14. 日志与可观测性规范
项目已引入 `spring-boot-starter-actuator`,因此新增模块应具备基本可观测性意识。
要求:
- 业务异常使用统一异常体系,不在正常分支打 error 日志
- 大查询、长耗时任务、批量处理建议记录 info/debug 级别日志
- 不记录敏感字段原文
- 生产问题定位优先结合 Actuator、日志、SQL 条件进行
建议:
- 对复杂迁移接口记录关键参数与结果数量
- 对导入、导出、批处理记录耗时
## 15. 安全规范
由于项目已引入 Spring Security新增模块应遵循最小暴露原则。
要求:
- Swagger/OpenAPI 文档在生产环境应受控
- 任何写接口必须考虑权限控制与审计要求
- 参数校验必须前置,避免越权探测和异常信息泄露
- 对动态 SQL 特别关注注入风险,所有用户输入都必须通过参数绑定
## 16. 测试规范
### 16.1 必测场景
新增业务模块至少要验证:
- 正常查询
- 必填参数缺失
- 空数据返回
- 关键筛选条件命中
- 排序/分页正确
### 16.2 测试建议
- 单表 CRUD 模块:优先补 Service/Mapper 单元或集成测试
- 迁移型查询模块:至少保留典型请求体样例和 SQL 验证说明
- 高风险接口:建议补接口级集成测试
### 16.3 不建议
- 为了补测试而写无价值的样板测试
- 完全重复实现逻辑本身的测试
## 17. 性能规范
### 17.1 查询性能
- 优先明确主表与过滤条件
- 少用无必要的多层嵌套子查询
- 大表统计优先关注时间条件、站点条件、逻辑删除条件是否下推
- `ROWNUM = 1`、`FETCH FIRST 1 ROWS ONLY` 等默认值查询必须确保排序稳定
### 17.2 Java 21 使用建议
本项目使用 Java 21但业务模块默认仍以同步 MVC 为主。
建议:
- 普通查询接口保持同步风格,避免过早引入响应式复杂度
- CPU 密集或 I/O 密集的异步能力需经过明确评估后再引入
- 语言特性应以可读性优先,避免为了“新语法”牺牲团队可维护性
## 18. 新增业务模块推荐模板
### 18.1 基础管理模块模板
- `domain/Xxx.java`
- `mapper/XxxMapper.java`
- `service/IXxxService.java`
- `service/impl/XxxServiceImpl.java`
- `controller/XxxController.java`
适用:
- 国家、流域、字典、基础表管理
### 18.2 复杂查询模块模板
- `entity/vo/XxxVO.java`
- `mapper/XxxMapper.java`
- `service/XxxService.java`
- `service/impl/XxxServiceImpl.java`
- `controller/XxxController.java`
适用:
- 旧平台迁移
- 统计分析
- 图表联查
- 多表业务判断
## 19. 开发禁止项
以下行为在新增业务模块中原则上禁止:
- Controller 直接操作 Mapper
- 直接返回裸 `Map` 作为通用接口响应
- 大量复制旧 SQL 但不校验字段语义
- 将前端字段名直接拼成 SQL 片段
- 业务异常使用 `RuntimeException`
- 多个接口返回结构风格不统一
- 在 Service 中堆积无法复用、语义不清的“万能工具方法”
- 未确认表语义就擅自把旧表字段映射到新表字段
- 对外接口无 `@Operation` 文档说明
## 20. 迁移模块专项检查清单
新增或改造迁移模块时,提交前必须自检:
- 是否定位了旧入口 Controller/Service/Mapper/XML
- 是否梳理了旧表职责与表关系
- 是否建立了旧表到新表的映射说明
- 是否保持了旧接口路径、入参名、返回字段的兼容性
- 是否校验了关键 SQL 的过滤条件、排序条件和时间口径
- 是否补充了空值、默认值、无数据场景处理
- 是否检查了 `IS_DELETED`、`USFL`、`MWAY`、`DTIN_TYPE` 等业务条件
- 是否校验了 `ResponseResult`、`DataSourceResult`、VO 返回结构
- 是否完成最基本的诊断或测试验证
## 21. 推荐落地原则
本项目业务模块开发建议遵循以下顺序:
1. 先确认业务语义与表关系
2. 再确定模块属于 CRUD 型还是迁移查询型
3. 再选择 MyBatis-Plus、注解 SQL 或动态 SQL
4. 再定义 VO/Domain/Service/Controller 落位
5. 最后补异常、文档、校验、测试与性能检查
一句话原则:
以项目现有架构为主线,以 Spring Boot 4.0 现代实践为约束以“业务语义正确、接口兼容、SQL 可维护、结构可复用”为最终标准。
## 22. 附录:外部参考资料
- Spring Boot Documentation Overview
- https://docs.spring.io/spring-boot/documentation.html
- springdoc OpenAPI Getting Started
- https://springdoc.org/getting-started.html
- MyBatis-Plus Quick Start
- https://baomidou.com/en/getting-started/
- MyBatis Spring Boot Starter Reference
- https://mybatis.org/spring-boot-starter/mybatis-spring-boot-autoconfigure/