# 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`,本项目业务开发技术基线如下: - JDK:21 - Spring Boot:4.0.3 - Spring Web:MVC - Spring Security:已引入 - Springdoc OpenAPI:3.0.2 - MyBatis:3.5.16 - MyBatis Spring Boot Starter:4.0.1 - MyBatis-Plus:3.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` - 使用 `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// 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` 作为常规入参 - `Map` 仅用于动态字段更新、非结构化补丁写入等少数场景 ## 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` 绑定,禁止字符串直接拼接用户输入 - 非必要不要在 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/