# Java 后端开发规范

## 制定背景

提供一套可复用的标准化开发规范，适用于 Spring Boot 企业级应用开发。

## 核心原则

1. **OpenAPI 规范驱动** - 前后端通过接口规范对齐，零沟通成本
2. **类型安全优先** - TypeScript 强制类型校验，早发现早修复
3. **约定大于配置** - 统一代码风格和目录结构，降低认知负担
4. **自动化优先** - 能自动化的绝不手动（代码生成、部署、测试）
5. **三层架构分离** - Controller、Service、Mapper 职责清晰

---

## 一、技术栈规范

### 后端技术栈

| 组件 | 技术选型 | 版本 | 说明 |
|:------|:------|:------|:------|
| 框架 | Spring Boot | 3.2+ | 基于 Java 17 |
| 持久层 | MyBatis-Plus | 3.5+ | 简化 CRUD |
| 对象映射 | MapStruct | 1.5+ | VO/Entity 转换 |
| 数据库连接池 | Alibaba Druid | 1.2+ | 数据库连接池 + 监控 |
| 安全 | Spring Security + JWT | - | 无状态认证 |
| API 文档 | Knife4j (SpringDoc) | 4.x | OpenAPI 3.0 |
| 数据库 | MySQL | 8.0+ | 关系型数据库 |
| 迁移 | Flyway | - | 版本化数据库变更 |
| 校验 | Hibernate Validator | - | JSR-303 参数校验 |
| 缓存 | Redis + Spring Data Redis | - | 缓存、会话存储 |
| 日志 | Logback | - | 结构化日志 |
| JSON | FastJSON | 2.x | JSON 序列化 |
| 工具类 | Hutool | 5.x | 常用工具集合 |
| 文件存储 | 阿里云 OSS | - | 对象存储 |

---

## 二、项目结构规范

### 后端目录结构

主要模块包括 common（公共模块）、controller（控制器层）、service（服务层）、mapper（数据访问层）、entity（实体类）、dto（数据传输对象）、enums（枚举类）。资源配置包括 application 配置文件、Flyway 迁移脚本、日志配置、MyBatis XML。

---

## 三、三层架构规范

### 各层职责

| 层级 | 职责 | 数据接收 | 数据返回 |
|:------|:------|:---------|:---------|
| **Controller** | 接收请求、参数校验、调用 Service、返回响应 | DTO/Request | VO/Response |
| **Service** | 处理业务逻辑、事务控制 | DTO/Entity | Entity |
| **Mapper** | 数据库 CRUD 操作 | Entity/条件 | Entity |

### 核心规范

1. **Service/Mapper 层必须使用实体类** - Service↔Mapper 之间只用 Entity，禁止 DTO/VO 转换
2. **转换只在 Controller 层发生** - Entity ↔ VO 转换统一在 Controller 层处理
3. **Service 继承 IService<T>** - 所有 Service 接口继承 MyBatis-Plus 的 IService
4. **查询接口默认分页** - 所有返回列表的查询接口，默认进行分页处理

### 查询方式选择

| 场景 | 推荐方式 |
|:------|:---------|
| 单表按 ID 查询 | 通用方法 `getById(id)` |
| 单表条件查询 | QueryWrapper `list(wrapper)` / `getOne(wrapper)` |
| 单表分页查询 | QueryWrapper + Page `page(new Page<>(p, s), wrapper)` |
| 单表统计 | QueryWrapper `count(wrapper)` |
| 两表联查 | 自定义 SQL `mapper.selectWithXxx()` |
| 三表及以上 | 自定义 SQL |
| 聚合统计 | 自定义 SQL |
| 动态复杂条件 | 自定义 SQL(XML) |

### 消除魔法值规范

**核心原则：禁止在代码中使用魔法值，所有状态、类型、常量必须使用枚举定义**

| 场景 | 规范 |
|:------|:------|
| 状态字段 | 使用枚举定义（如 `CommonStatusEnum`） |
| 类型字段 | 使用枚举定义（如 `UserTypeEnum`） |
| 常量值 | 使用常量类或接口定义 |
| 错误码 | 使用枚举定义（如 `ErrorCode`） |

**枚举设计规范：**
- 枚举类统一存放在 `enums` 包下
- 枚举包含 `code` 和 `desc` 字段，便于前端展示
- 提供 `getCode()`、`getDesc()`、`valueOfCode()` 方法
- 数据库存储 `code`，代码中使用枚举

---

## 四、ORM 实体类规范

### 1. 表名命名规范

所有数据库表必须添加业务模块前缀，格式为 `t_{模块}_{表名}`：

| 模块分类 | 前缀 | 示例 |
|:------|:------|:------|
| 用户模块 | t_user_ | t_user, t_user_role |
| 系统模块 | t_sys_ | t_sys_config, t_sys_log |
| 业务模块 | t_biz_ | t_biz_order, t_biz_product |
| 权限模块 | t_auth_ | t_auth_role, t_auth_menu |

### 2. 表名与实体类名对应规范

**表名与实体类名必须保持一致**，仅允许下划线与驼峰的区别：

| 表名（下划线命名） | 实体类名（驼峰命名） |
|:------|:------|
| `t_auth_role` | `AuthRole` |
| `t_user_role` | `UserRole` |
| `t_sys_config` | `SysConfig` |

### 3. 不使用外键约束规范

- 数据库表之间**不使用 FOREIGN KEY 外键约束**
- 表与表之间的关联关系通过**代码逻辑控制**
- 关联查询通过 `JOIN` 或应用层组装实现

### 4. 多对多关系中间表命名规范

**核心原则：中间表名必须清晰表达两个关联实体的关系**

- 标准命名格式：`t_{实体 A}_{实体 B}`
- 按字母顺序或业务逻辑顺序排列
- 不使用 `relation`、`rel`、`link` 等冗余词
- 实体类名直接使用两个实体名的组合（如 `ParentStudent`）

### 5. 基础实体类

所有实体类继承 `BaseEntity`，包含公共字段：

| 字段 | 类型 | 说明 | 自动填充 |
|:------|:------|:------|:------|
| id | Long | 主键 ID（自增） | 数据库自增 |
| createBy | String | 创建人 | 插入时 |
| createTime | LocalDateTime | 创建时间 | 插入时 |
| updateBy | String | 更新人 | 更新时 |
| updateTime | LocalDateTime | 更新时间 | 更新时 |
| deleted | Integer | 逻辑删除标识 | - |

### 6. 审计字段规范

**所有数据库表必须包含审计字段**，用于追踪数据变更历史：

| 审计字段 | 类型 | 说明 | 必填 |
|:------|:------|:------|:------|
| create_by | VARCHAR(50) | 创建人账号 | 是 |
| create_time | DATETIME | 创建时间 | 是 |
| update_by | VARCHAR(50) | 更新人账号 | 是 |
| update_time | DATETIME | 更新时间 | 是 |
| deleted | TINYINT | 逻辑删除标识（0-未删除，1-已删除） | 是 |

**规范要求：**
- 审计字段通过 MyBatis-Plus `FieldFill` 自动填充
- 禁止在业务代码中手动设置审计字段
- 生产环境审计字段不得为空

---

## 五、日志规范

### 1. 日志语言规范（重要）

**所有日志打印内容必须使用中文**

| 场景 | 推荐格式 | 示例 |
|:------|:------|:------|
| 操作开始 | "开始{操作}，{关键参数}" | `开始创建用户，用户名：zhangsan` |
| 操作成功 | "{操作}成功，{关键结果}" | `用户创建成功，ID: 123` |
| 操作失败 | "{操作}失败，{关键参数}" | `用户删除失败，ID: 123` |
| 查询操作 | "{动作}{对象}，{关键参数}" | `查询用户，ID: 123` |
| 状态检查 | "{对象}不存在/已存在，{关键参数}" | `用户不存在，ID: 123` |
| 异常日志 | "{操作}异常，{关键参数}" + e | `创建用户异常，ID: 123` + e |

### 2. 日志级别使用场景

| 级别 | 使用场景 |
|:------|:------|
| ERROR | 系统异常，需要人工介入（数据库连接失败、第三方服务调用失败） |
| WARN | 业务异常，可预期的错误（参数校验失败、资源不存在） |
| INFO | 重要的业务操作记录（用户登录、订单创建、支付完成） |
| DEBUG | 调试信息，开发时使用（方法入参、SQL 执行结果） |

### 3. TraceId 链路追踪规范

- 使用 `MDC`（Mapped Diagnostic Context）实现 TraceId 链路追踪
- 通过 AOP 切面在请求入口自动生成 TraceId 并放入 MDC
- 请求结束时清除 MDC，防止内存泄漏
- 日志格式包含 `[%X{traceId}]` 实现全链路追踪

### 4. 环境差异化日志配置

| 环境 | 日志策略 |
|:------|:------|
| **开发/测试环境** | 全量记录（DEBUG 级别），包含所有业务日志、SQL 日志、调试信息 |
| **生产环境** | 精简记录（INFO/WARN 级别），仅记录：请求日志、错误堆栈、错误 SQL、关键业务操作 |

### 5. AOP 日志实现规范

- 使用 `@Aspect` 定义日志切面，拦截 Controller 层所有方法
- 请求日志包含：TraceId、请求方法、请求路径、IP、耗时
- 异常日志包含：TraceId、异常类型、异常消息、堆栈信息
- 生产环境关闭 DEBUG 日志，避免性能损耗和日志膨胀

---

## 六、统一响应格式

### 1. 响应类定义

Result 统一响应类包含 code（状态码）、message（消息）、data（数据）、timestamp（时间戳）字段。

### 2. 错误码枚举

| 错误码 | 说明 |
|:------|:------|
| 200 | 成功 |
| 400 | 请求参数错误 |
| 401 | 未登录或 Token 已过期 |
| 403 | 没有访问权限 |
| 404 | 资源不存在 |
| 500 | 系统内部错误 |

### 3. 全局异常处理器

- 使用 `@RestControllerAdvice` 定义全局异常处理器
- 业务异常返回对应错误码
- 系统异常统一返回 500

---

## 七、多环境配置规范

### 1. 配置文件目录结构

配置文件包括 application.yml（主配置）、application-dev.yml（开发环境）、application-test.yml（测试环境）、application-prod.yml（生产环境）。

### 2. 环境配置对比

| 配置项 | 开发环境 (dev) | 测试环境 (test) | 生产环境 (prod) |
|:------|:------|:------|:------|
| 数据库 | 本地 MySQL | 测试服务器 | 生产服务器 |
| SQL 日志 | 开启 | 开启 | 关闭 |
| Swagger | 开启 | 开启 | 关闭 |
| Flyway Clean | 允许 | 禁止 | 禁止 |
| JWT 密钥 | 默认值 | 默认值 | 必须环境变量 |
| Redis 连接池 | 默认 | 默认 | 优化配置 |

### 3. 环境切换方式

- 方式一：环境变量 `export SPRING_PROFILES_ACTIVE=prod`
- 方式二：命令行参数 `java -jar project.jar --spring.profiles.active=prod`

---

## 八、工具类使用规范

### 1. 工具函数存放位置

| 场景 | 存放位置 |
|:------|:------|
| 多个地方调用（≥2 处） | 统一工具类（如 `CommonUtil`） |
| 仅在一个地方调用 | Service 层内部私有方法 |
| 业务无关的通用工具 | 独立工具类（如 `DateUtil`, `FileUtil`） |

### 2. 工具类设计原则

- **私有构造** - 防止实例化
- **静态方法** - 所有方法都是 `static` 的
- **无状态** - 工具类不应持有状态
- **线程安全** - 工具方法必须是线程安全的
- **充分注释** - 每个方法都要有 JavaDoc 注释

### 3. 工具类命名规范

| 类型 | 命名格式 | 示例 |
|:------|:------|:------|
| 通用工具类 | `XxxUtil` | `CommonUtil`, `DateUtil`, `FileUtil` |
| 业务工具类 | `XxxHelper` | `UserHelper`, `OrderHelper` |
| 转换工具类 | `XxxConverter` | `EntityConverter`, `DtoConverter` |

---

## 九、MapStruct 对象映射规范

### 1. Maven 依赖

```xml
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct</artifactId>
    <version>1.5.5.Final</version>
</dependency>
```

### 2. 使用规范

- 定义 Converter 接口，使用 `@Mapper` 注解
- 接口方法用于 Entity ↔ VO 之间的转换
- 在 Controller 层调用 Converter 进行对象转换
- 禁止在 Service 层和 Mapper 层进行 DTO/VO 转换

### 3. 命名规范

| 类型 | 命名格式 | 示例 |
|:------|:------|:------|
| 对象映射接口 | `XxxConverter` 或 `XxxMapStruct` | `UserConverter`, `OrderConverter` |

---

## 十、Hutool 工具类使用

### 常用工具方法

- 生成 UUID（不带横杠）：`IdUtil.fastSimpleUUID()`
- 密码加密（BCrypt）：`SecureUtil.bcrypt(password)`
- 密码校验：`SecureUtil.bcryptVerify(password, encrypted)`
- 手机号验证：`Validator.isMatchRegex("^1[3-9]\\d{9}$", phone)`
- 手机号脱敏：`DesensitizedUtil.mobilePhone(phone)`

---

## 十、Swagger/Knife4j 配置规范

### 1. 接口文档访问

- Knife4j UI: `http://localhost:8080/doc.html`
- OpenAPI JSON: `http://localhost:8080/v3/api-docs`

### 2. Controller 层注解

- 使用 `@Tag` 注解标注控制器
- 使用 `@Operation` 注解标注接口
- 使用 `@Schema` 注解标注 DTO 字段

---

## 十一、工具函数使用规范

**核心原则：工具函数必须集中管理，禁止在 Controller 层直接编写工具方法**

### 工具函数存放位置

| 场景 | 存放位置 |
|:------|:------|
| 多个地方调用（≥2 处） | 统一工具类（如 `CommonUtil`） |
| 仅在一个地方调用 | Service 层内部私有方法 |
| 业务无关的通用工具 | 独立工具类（如 `DateUtil`, `FileUtil`） |

### 工具类命名规范

| 类型 | 命名格式 | 示例 |
|:------|:------|:------|
| 通用工具类 | `XxxUtil` | `CommonUtil`, `DateUtil`, `FileUtil` |
| 业务工具类 | `XxxHelper` | `UserHelper`, `OrderHelper` |
| 转换工具类 | `XxxConverter` | `EntityConverter`, `DtoConverter` |

---

## 十二、限流规范

### 技术选型

| 方案 | 适用场景 |
|:------|:------|
| **Redis 滑动窗口** | 推荐：全局限流 |
| **自定义注解 + AOP** | 推荐：特殊接口限流 |

### 常见限流场景建议值

| 接口类型 | 时间窗口 | 最大请求数 | 说明 |
|:------|:------|:------|:------|
| 登录接口 | 60 秒 | 10 | 防止暴力破解 |
| 验证码/短信 | 60 秒 | 3-5 | 防止短信轰炸 |
| 文件上传 | 60 秒 | 30 | 防止资源滥用 |
| 普通业务接口 | 60 秒 | 100-1000 | 根据业务调整 |
| 导出接口 | 60 秒 | 5-10 | 防止服务器过载 |

---

## 十三、FastJSON 配置规范

### JSON 工具类

- `toJson(Object)` - 对象转 JSON 字符串
- `parseObject(String, Class)` - JSON 字符串转对象
- `parseArray(String, Class)` - JSON 字符串转列表

---

## 十四、阿里云 OSS 文件上传规范

### OSS 配置

配置项包括 endpoint、access-key-id、access-key-secret、bucket-name、url-prefix，均通过环境变量注入。

### 文件命名规范

- 使用日期目录：`yyyy/MM/dd/`
- 使用 UUID 文件名，避免重名冲突

---

## 附录：快速参考

### 表名命名规范

- `t_user_*` - 用户模块
- `t_sys_*` - 系统模块
- `t_biz_*` - 业务模块
- `t_auth_*` - 权限模块

### Redis Key 命名规范

- `auth:token:{token}` - 用户 Token
- `user:info:{userId}` - 用户信息缓存
- `dict:{type}` - 数据字典
- `lock:{resource}:{id}` - 分布式锁
- `rate_limit:{key}` - 限流计数器

### 核心配置速查

| 配置项 | 环境变量 |
|:------|:------|
| 活跃环境 | `SPRING_PROFILES_ACTIVE` |
| 数据库地址 | `DB_HOST` |
| 数据库密码 | `DB_PASSWORD` |
| Redis 地址 | `REDIS_HOST` |
| Redis 密码 | `REDIS_PASSWORD` |
| JWT 密钥 | `JWT_SECRET` |
| OSS AccessKey | `OSS_ACCESS_KEY_ID` |
| OSS Secret | `OSS_ACCESS_KEY_SECRET` |
