WholeProcessPlatform/backend/docs/业务模块开发技术规范.md

580 lines
17 KiB
Markdown
Raw Permalink Normal View History

2026-05-21 11:35:09 +08:00
# 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/