Files
his/MD/specs/BACKEND_DEVELOPMENT_STANDARD.md
华佗 3578a24254 docs(specs): 汇总铁律和前后端开发规范文档到MD目录
- 新增 MD/specs/IRON_RULES.md — 执行铁律汇总(v2.0, 8条铁律)
- 新增 MD/specs/BACKEND_DEVELOPMENT_STANDARD.md — 后端开发规范
- 新增 MD/specs/FRONTEND_DEVELOPMENT_STANDARD.md — 前端开发规范
- 新增 healthlink-his-ui/AGENTS.md — 前端铁律引用
- 更新 healthlink-his-server/AGENTS.md — 同步规范文档引用
- 修复10个文档缺失的元数据(文档类型标签)
- 全部30个文档通过命名规范和元数据检查
2026-06-06 09:33:20 +08:00

368 lines
10 KiB
Markdown
Raw 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.

# 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<RegistrationDto> 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<PatientDto> list) {
for (PatientDto dto : list) {
this.insert(dto); // 自调用,事务不生效!
}
}
```
### 5.3 Mapper 规范
```java
// ✅ 正确 - 使用LambdaQueryWrapper
public List<Patient> selectList(PatientQueryDto query) {
LambdaQueryWrapper<Patient> 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<Patient> 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 格式
```
<type>(<scope>): <subject>
<body>
<footer>
```
### Type 类型
| Type | 说明 |
|------|------|
| feat | 新功能 |
| fix | Bug修复 |
| docs | 文档变更 |
| style | 代码格式不影响功能 |
| refactor | 重构 |
| test | 测试相关 |
| chore | 构建/工具变更 |
### 示例
```
feat(registration): 新增患者过敏史管理功能
- 新增 PatientAllergy 实体和 Mapper
- 新增 IRegistrationAppService.getPatientAllergy()
- 新增 /api/v1/registration/allergy 接口
- Flyway迁移脚本: V2.0.1__add_patient_allergy.sql
Co-authored-by: zhangsan <zhangsan@healthlink.com>
```
---
> **文档版本**: v1.0
> **最后更新**: 2026-06-06