# HealthLink-HIS 后端开发规范 > **文档类型**: 技术规范 > **适用范围**: 后端 Java 开发 > **版本**: v1.0 > **编制日期**: 2026-06-06 > **最后更新**: 2026-06-06 --- ## 一、技术栈 | 组件 | 版本 | 说明 | |------|------|------| | JDK | 25 | OpenJDK 25 (LTS) | | Spring Boot | 4.0.6 | 框架核心 | | MyBatis-Plus | 3.5.16 | ORM框架 | | PostgreSQL | 15+ | 主数据库 | | Redis | 7.x | 缓存/会话 | | Maven | 3.9+ | 构建工具 | --- ## 二、项目结构 ``` healthlink-his-server/ ├── healthlink-his-common/ # 公共模块(枚举、常量、工具类) ├── healthlink-his-domain/ # 领域层(实体、Mapper、Flyway迁移) ├── healthlink-his-application/ # 应用层(Controller、Service、业务逻辑) ├── core-common/ # 若依公共核心 ├── core-system/ # 若依系统模块 ├── core-framework/ # 若依框架核心 ├── core-quartz/ # 定时任务 ├── core-generator/ # 代码生成 ├── core-flowable/ # 工作流 └── core-admin/ # 管理后台 ``` --- ## 三、分层架构规范 ### 3.1 Controller 层 - 路径:`com.healthlink.his.web.{module}.controller` - 职责:接收请求、参数校验、调用AppService、返回统一结果 - 禁止:直接操作数据库、编写业务逻辑 ```java @RestController @RequestMapping("/api/v1/registration") @Api(tags = "挂号管理") public class RegistrationController { @Autowired private IRegistrationAppService registrationAppService; @GetMapping("/list") @PreAuthorize("@ss.hasPermi('registration:list')") public TableDataInfo list(RegistrationQueryDto query) { startPage(); List list = registrationAppService.selectList(query); return getDataTable(list); } } ``` ### 3.2 AppService 层(应用服务) - 路径:`com.healthlink.his.web.{module}.appservice` - 职责:编排业务流程、协调多个Service、事务管理 - 命名:`XxxAppService`(接口)+ `XxxAppServiceImpl`(实现) ### 3.3 Service 层 - 路径:`com.healthlink.his.web.{module}.service` - 职责:单表CRUD、基础业务逻辑 - 命名:`IXxxService`(接口)+ `XxxServiceImpl`(实现) ### 3.4 Mapper 层 - 路径:`com.healthlink.his.web.{module}.mapper` - 职责:数据访问、SQL映射 - 命名:`XxxMapper`(接口)+ `XxxMapper.xml`(XML映射) ### 3.5 Entity/Domain 层 - 路径:`com.healthlink.his.domain.{module}` - 职责:实体定义、数据库表映射 - 命名:`Xxx`(实体类) ### 3.6 DTO 层 - 路径:`com.healthlink.his.web.{module}.dto` - 职责:数据传输对象、查询参数、返回结果 --- ## 四、命名规范 ### 4.1 包命名 ``` com.healthlink.his.web.{模块名}.{层级} ``` ### 4.2 类命名 | 类型 | 命名规则 | 示例 | |------|---------|------| | Controller | `XxxController` | `RegistrationController` | | AppService接口 | `IXxxAppService` | `IRegistrationAppService` | | AppService实现 | `XxxAppServiceImpl` | `RegistrationAppServiceImpl` | | Service接口 | `IXxxService` | `IRegistrationService` | | Service实现 | `XxxServiceImpl` | `RegistrationServiceImpl` | | Mapper | `XxxMapper` | `RegistrationMapper` | | Entity | `Xxx` | `Registration` | | DTO | `XxxDto` / `XxxQueryDto` | `RegistrationDto` | | Enum | `XxxEnum` / `XxxType` | `ItemType` | ### 4.3 方法命名 | 场景 | 命名规则 | 示例 | |------|---------|------| | 查询列表 | `selectList` / `queryList` | `selectList(query)` | | 查询详情 | `selectById` / `getById` | `selectById(id)` | | 新增 | `insert` / `save` / `add` | `insert(dto)` | | 修改 | `update` / `modify` | `update(dto)` | | 删除 | `delete` / `remove` | `deleteById(id)` | | 批量操作 | `batchXxx` | `batchInsert(list)` | ### 4.4 数据库命名 | 类型 | 命名规则 | 示例 | |------|---------|------| | 表名 | `{模块}_{功能}` 小写下划线 | `reg_registration` | | 字段名 | 小写下划线 | `patient_id`, `create_time` | | 主键 | `id` 或 `{表名}_id` | `registration_id` | | 外键 | `{关联表}_id` | `patient_id` | | 时间字段 | `create_time`, `update_time` | — | | 软删除 | `del_flag` | — | | 租户 | `tenant_id` | — | --- ## 五、编码规范 ### 5.1 Controller 规范 ```java // ✅ 正确 @RestController @RequestMapping("/api/v1/patient") @Api(tags = "患者管理") @Slf4j public class PatientController { @Autowired private IPatientAppService patientAppService; @GetMapping("/{id}") @PreAuthorize("@ss.hasPermi('patient:query')") public AjaxResult getInfo(@PathVariable Long id) { return success(patientAppService.selectById(id)); } @PostMapping @PreAuthorize("@ss.hasPermi('patient:add')") public AjaxResult add(@Validated @RequestBody PatientDto dto) { return toAjax(patientAppService.insert(dto)); } } // ❌ 错误 - Controller里写业务逻辑 public AjaxResult add(@RequestBody PatientDto dto) { // 不应该在这里写验证逻辑 if (dto.getName() == null) { return error("名称不能为空"); } // 不应该在这里写数据库操作 patientMapper.insert(patient); return success(); } ``` ### 5.2 Service 规范 ```java // ✅ 正确 - 事务注解 @Transactional(rollbackFor = Exception.class) public int insert(PatientDto dto) { Patient patient = BeanUtils.copyProperties(dto, Patient.class); patient.setCreateTime(new Date()); patient.setCreateBy(SecurityUtils.getUsername()); return patientMapper.insert(patient); } // ❌ 错误 - 自调用导致事务失效 public void batchProcess(List list) { for (PatientDto dto : list) { this.insert(dto); // 自调用,事务不生效! } } ``` ### 5.3 Mapper 规范 ```java // ✅ 正确 - 使用LambdaQueryWrapper public List selectList(PatientQueryDto query) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.like(StringUtils.isNotBlank(query.getName()), Patient::getName, query.getName()) .eq(Patient::getDelFlag, "0") .orderByDesc(Patient::getCreateTime); return patientMapper.selectList(wrapper); } // ❌ 错误 - 字符串拼接SQL public List selectList(String name) { String sql = "SELECT * FROM patient WHERE name = '" + name + "'"; return jdbcTemplate.queryForList(sql, Patient.class); } ``` ### 5.4 统一返回格式 ```java // 成功 return AjaxResult.success(data); return AjaxResult.success("操作成功", data); // 失败 return AjaxResult.error("患者不存在"); return AjaxResult.error(MessageUtils.message("patient.not.found")); // 列表 TableDataInfo dataPage = getDataTable(list); ``` --- ## 六、异常处理规范 ### 6.1 业务异常 ```java throw new ServiceException("患者编号不能为空"); throw new ServiceException(MessageUtils.message("patient.id.required")); ``` ### 6.2 全局异常处理 - 使用 `@RestControllerAdvice` + `@ExceptionHandler` - 不在 Controller 中 try-catch 后返回错误 - 所有异常最终返回统一格式 `{code, msg, data}` ### 6.3 日志规范 ```java // ✅ 正确 log.info("患者挂号成功: patientId={}, registrationId={}", patientId, regId); log.error("挂号失败: patientId={}", patientId, e); // ❌ 错误 log.info("患者身份证号: " + idCard); // 敏感信息泄露 System.out.println("debug"); // 不使用System.out ``` --- ## 七、安全规范 ### 7.1 数据脱敏 - 患者身份证号:`***` 掩码 - 患者手机号:前3后4,中间 `****` - 密码:BCrypt 加密,不可逆 ### 7.2 SQL注入防护 - 所有查询使用参数化查询 - 禁止字符串拼接 SQL - 使用 MyBatis-Plus 的 `QueryWrapper` / `LambdaQueryWrapper` ### 7.3 权限控制 - 所有接口标注 `@PreAuthorize` - 数据级权限校验(医生只能访问本科室患者) - 敏感操作需二次确认 --- ## 八、测试规范 ### 8.1 测试类型 | 类型 | 工具 | 覆盖范围 | |------|------|---------| | 单元测试 | JUnit 5 + Mockito | Service/工具类 | | 接口测试 | MockMvc + SpringBootTest | Controller接口 | | 白盒测试 | Maven编译 | 全量代码 | | 黑盒测试 | 手动/自动化 | 核心业务流程 | ### 8.2 接口测试规范 ```java @SpringBootTest @AutoConfigureMockMvc public class PatientApiTest { @Test public void testGetPatientInfo() throws Exception { mockMvc.perform(get("/healthlink-his/api/v1/patient/{id}", 1L) .header("Authorization", "Bearer " + token)) .andExpect(status().isOk()) .andExpect(jsonPath("$.code").value(200)) .andExpect(jsonPath("$.data").isNotEmpty()) .andExpect(jsonPath("$.data.name").isNotEmpty()); } } ``` ### 8.3 测试数据要求 - 测试数据必须基于业务逻辑设计 - 验证业务返回内容(非仅HTTP状态码) - 覆盖正常流程和异常流程 - 包含边界条件测试 --- ## 九、性能规范 ### 9.1 数据库查询 - 无N+1查询问题(使用 `JOIN` 或批量查询) - 大表查询必须有分页限制 - 慢查询已优化(执行时间 < 500ms) - 索引已覆盖高频查询条件 ### 9.2 接口性能 - 核心接口响应时间 < 1秒 - 列表接口支持分页,无全量返回 - 大文件下载使用流式传输 ### 9.3 缓存使用 - 频繁查询的字典数据使用Redis缓存 - 缓存必须设置过期时间 - 数据变更时主动清除相关缓存 --- ## 十、Git提交规范 ### Commit Message 格式 ``` ():