You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
26 KiB
26 KiB
开发规范
**本文引用的文件** - [CrmAppApplication.java](file://crm-app/src/main/java/com/crm/app/CrmAppApplication.java) - [application.yml](file://crm-app/src/main/resources/application.yml) - [AuthApplication.java](file://crm-auth/src/main/java/com/crm/auth/AuthApplication.java) - [application.yml](file://crm-auth/src/main/resources/application.yml) - [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java) - [OwnedEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/OwnedEntity.java) - [BaseDTO.java](file://crm-base/src/main/java/com/crm/base/domain/dto/BaseDTO.java) - [BaseParam.java](file://crm-base/src/main/java/com/crm/base/domain/param/BaseParam.java) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java) - [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [BusinessErrorException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/BusinessErrorException.java) - [MissingParameterException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/MissingParameterException.java) - [PermissionErrorException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/PermissionErrorException.java) - [ResourceNotExistException.java](file://crm-base/src/main/java/com/crm/base/domain/exception/ResourceNotExistException.java) - [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java) - [DataOwnership.java](file://crm-base/src/main/java/com/crm/base/security/DataOwnership.java) - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataScopeLevel.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeLevel.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java) - [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java) - [TraceIdFilter.java](file://crm-base/src/main/java/com/crm/base/filter/TraceIdFilter.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java) - [SnowflakeIdWorker.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java) - [CustomIdGenerator.java](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java) - [AuthService.java](file://crm-auth/src/main/java/com/crm/auth/service/IAuthService.java) - [AuthServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/AuthServiceImpl.java) - [AuthController.java](file://crm-auth/src/main/java/com/crm/auth/controller/AuthController.java) - [JwtAuthenticationFilter.java](file://crm-auth/src/main/java/com/crm/auth/security/JwtAuthenticationFilter.java) - [TokenService.java](file://crm-auth/src/main/java/com/crm/auth/security/TokenService.java) - [SecurityExceptionHandlers.java](file://crm-auth/src/main/java/com/crm/auth/security/SecurityExceptionHandlers.java) - [LoginParam.java](file://crm-auth/src/main/java/com/crm/auth/domain/param/LoginParam.java) - [LoginResultDTO.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/LoginResultDTO.java) - [UserInfoDTO.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/UserInfoDTO.java) - [AuthUser.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/AuthUser.java) - [AuthIdentity.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/AuthIdentity.java) - [SysDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysDept.java) - [SysMenu.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysMenu.java) - [SysRole.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysRole.java) - [SysRoleMenu.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysRoleMenu.java) - [SysUserDept.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserDept.java) - [SysUserRole.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysUserRole.java) - [DataScopeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/DataScopeEnum.java) - [IdentityTypeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/IdentityTypeEnum.java) - [MenuTypeEnum.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/MenuTypeEnum.java) - [FileApi.java](file://crm-file/src/main/java/com/crm/file/api/FileApi.java) - [FileController.java](file://crm-file/src/main/java/com/crm/file/controller/FileController.java) - [FileInfo.java](file://crm-file/src/main/java/com/crm/file/domain/entity/FileInfo.java) - [IFileInfoService.java](file://crm-file/src/main/java/com/crm/file/service/IFileInfoService.java) - [FileInfoServiceImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileInfoServiceImpl.java) - [FileApiImpl.java](file://crm-file/src/main/java/com/crm/file/service/impl/FileApiImpl.java) - [KkFileViewClient.java](file://crm-file/src/main/java/com/crm/file/service/KkFileViewClient.java) - [OrphanChunkCleanupTask.java](file://crm-file/src/main/java/com/crm/file/task/OrphanChunkCleanupTask.java) - [pom.xml](file://pom.xml)目录
简介
本规范面向 CRM 后端多模块工程,统一代码风格、命名约定、包结构、实体与数据传输对象设计、异常与日志规范、注释规范以及 Git 工作流与代码审查流程。目标是通过一致的编码标准提升代码质量、可维护性与团队协作效率。
项目结构
本项目采用多模块 Maven 工程,按领域与职责划分:
- crm-app:应用启动入口与全局配置
- crm-base:基础能力(通用实体、DTO/Param/Result、安全上下文、数据权限、异常、工具类、MyBatis Plus 配置)
- crm-auth:认证授权与系统管理(用户、角色、菜单、部门、第三方登录等)
- crm-file:文件服务(上传、分片、预览、清理任务等)
graph TB
subgraph "应用层"
APP["crm-app<br/>启动与配置"]
end
subgraph "业务域"
AUTH["crm-auth<br/>认证与系统管理"]
FILE["crm-file<br/>文件服务"]
end
subgraph "基础能力"
BASE["crm-base<br/>通用实体/DTO/Param/Result<br/>安全上下文/异常/工具/配置"]
end
APP --> AUTH
APP --> FILE
AUTH --> BASE
FILE --> BASE
图示来源
- CrmAppApplication.java
- AuthApplication.java
- pom.xml
章节来源
- CrmAppApplication.java
- AuthApplication.java
- pom.xml
核心组件
- 通用实体基类与数据所有权
- BaseEntity:统一审计字段(如创建时间、更新时间等),配合元数据填充处理器自动落库
- OwnedEntity:在 BaseEntity 基础上增加数据归属字段,结合数据可见性上下文实现行级数据权限控制
- 数据传输对象
- BaseDTO:通用 DTO 基类,用于接口返回或跨层传输
- BaseParam:通用请求参数基类,用于入参校验与封装
- Result/PageResult:统一响应包装与分页结果
- 安全与数据权限
- LoginUser/SecurityUtils:当前登录用户上下文获取
- DataOwnership/DataScope/DataScopeLevel/DataScopeHelper/DataVisibilityContext:数据权限注解、级别、辅助方法与上下文
- 异常体系
- BusinessErrorException/MissingParameterException/PermissionErrorException/ResourceNotExistException:业务、参数、权限、资源不存在等异常类型
- GlobalExceptionHandlerAdvice:全局异常处理,统一错误码与消息
- MyBatis Plus 增强
- MetaObjectFillHandler:自动填充审计字段
- SnowflakeIdWorker/CustomIdGenerator:分布式 ID 生成策略
- MybatisPlusConfig:MP 配置注入
章节来源
- BaseEntity.java
- OwnedEntity.java
- BaseDTO.java
- BaseParam.java
- Result.java
- PageResult.java
- ResultCodeEnum.java
- GlobalExceptionHandlerAdvice.java
- BusinessErrorException.java
- MissingParameterException.java
- PermissionErrorException.java
- ResourceNotExistException.java
- DataOwnership.java
- DataScope.java
- DataScopeLevel.java
- DataScopeHelper.java
- DataVisibilityContext.java
- LoginUser.java
- SecurityUtils.java
- MetaObjectFillHandler.java
- SnowflakeIdWorker.java
- CustomIdGenerator.java
- MybatisPlusConfig.java
架构总览
分层与边界:
- 表现层(Controller):接收请求、参数校验、调用 Service
- 服务层(Service):业务编排、事务边界、调用 Mapper 与外部客户端
- 持久层(Mapper):数据访问,基于 MyBatis Plus
- 安全与数据权限:过滤器/拦截器 + 注解 + 上下文,贯穿 Controller -> Service -> Mapper
- 基础设施:统一异常、日志追踪、ID 生成、分页、枚举、工具类
sequenceDiagram
participant Client as "客户端"
participant AuthCtrl as "认证控制器"
participant TokenSvc as "令牌服务"
participant AuthService as "认证服务"
participant DB as "数据库"
Client->>AuthCtrl : "POST /auth/login"
AuthCtrl->>AuthService : "验证用户名密码"
AuthService->>DB : "查询用户信息"
DB-->>AuthService : "用户记录"
AuthService-->>AuthCtrl : "用户信息"
AuthCtrl->>TokenSvc : "签发JWT"
TokenSvc-->>AuthCtrl : "令牌"
AuthCtrl-->>Client : "登录成功响应"
图示来源
- AuthController.java
- AuthService.java
- AuthServiceImpl.java
- TokenService.java
详细组件分析
实体类设计规范(BaseEntity 与 OwnedEntity)
- BaseEntity
- 职责:提供统一的审计字段(如创建人、创建时间、更新人、更新时间等)
- 使用方式:所有持久化实体继承 BaseEntity;配合元数据填充处理器自动设置审计字段
- 复杂度:O(1) 字段赋值,填充发生在插入/更新前
- OwnedEntity
- 职责:在 BaseEntity 基础上增加“数据所有者”字段,用于数据隔离与权限过滤
- 使用方式:需要数据归属控制的实体继承 OwnedEntity;结合 DataOwnership/DataScope 注解与上下文进行行级过滤
- 注意:避免在批量操作中遗漏数据所有者,确保上下文正确设置
classDiagram
class BaseEntity {
+审计字段集合
+默认填充逻辑
}
class OwnedEntity {
+数据所有者字段
+数据可见性关联
}
BaseEntity <|-- OwnedEntity : "继承"
图示来源
- BaseEntity.java
- OwnedEntity.java
章节来源
- BaseEntity.java
- OwnedEntity.java
- MetaObjectFillHandler.java
数据传输对象设计(DTO、Param、Result)
- BaseDTO
- 用途:作为通用 DTO 基类,承载接口返回数据或跨层传输数据
- 建议:仅包含必要字段,避免直接暴露实体内部结构
- BaseParam
- 用途:作为通用请求参数基类,承载入参校验与封装
- 建议:与表单/查询参数一一对应,必要时使用分组校验
- Result/PageResult
- 用途:统一 API 响应包装,包含状态码、消息、数据体;PageResult 扩展分页信息
- 建议:保持响应结构一致,便于前端解析与错误处理
- 枚举与常量
- ResultCodeEnum:统一错误码定义,避免硬编码
- 业务枚举:集中定义于 domain/enums 包下,保证一致性
classDiagram
class BaseDTO {
+通用DTO字段
}
class BaseParam {
+通用参数字段
+校验规则
}
class Result {
+状态码
+消息
+数据体
}
class PageResult {
+分页信息
+数据列表
}
class ResultCodeEnum {
+错误码定义
}
Result --> ResultCodeEnum : "引用"
PageResult --> Result : "扩展"
图示来源
- BaseDTO.java
- BaseParam.java
- Result.java
- PageResult.java
- ResultCodeEnum.java
章节来源
- BaseDTO.java
- BaseParam.java
- Result.java
- PageResult.java
- ResultCodeEnum.java
认证与鉴权流程
- 登录流程
- 控制器接收登录参数,调用认证服务验证用户
- 认证成功后由令牌服务签发 JWT,并返回给客户端
- 鉴权流程
- 请求进入时通过 JWT 过滤器解析令牌,构建登录用户上下文
- 数据权限通过 DataScope 注解与 DataOwnership 注解共同作用,结合 DataVisibilityContext 进行行级过滤
sequenceDiagram
participant Client as "客户端"
participant Filter as "JWT过滤器"
participant Ctrl as "业务控制器"
participant Svc as "业务服务"
participant MP as "MyBatis Plus"
Client->>Filter : "携带JWT的请求"
Filter->>Filter : "解析令牌与用户上下文"
Filter-->>Ctrl : "放行并注入上下文"
Ctrl->>Svc : "执行业务方法"
Svc->>MP : "执行SQL带数据权限条件"
MP-->>Svc : "返回受控数据"
Svc-->>Ctrl : "业务结果"
Ctrl-->>Client : "统一响应"
图示来源
- JwtAuthenticationFilter.java
- TokenService.java
- DataScope.java
- DataOwnership.java
- DataScopeHelper.java
- DataVisibilityContext.java
章节来源
- JwtAuthenticationFilter.java
- TokenService.java
- DataScope.java
- DataOwnership.java
- DataScopeHelper.java
- DataVisibilityContext.java
文件服务组件
- FileController:提供文件上传、下载、预览等接口
- IFileInfoService/FileInfoServiceImpl:文件信息管理与业务逻辑
- FileApiImpl:对外文件能力抽象实现
- KkFileViewClient:第三方文件预览客户端
- OrphanChunkCleanupTask:定时清理孤立分片任务
classDiagram
class FileController {
+上传接口
+下载接口
+预览接口
}
class IFileInfoService {
+文件信息管理
}
class FileInfoServiceImpl {
+实现文件业务逻辑
}
class FileApiImpl {
+对外API实现
}
class KkFileViewClient {
+预览客户端
}
class OrphanChunkCleanupTask {
+清理任务
}
FileController --> IFileInfoService : "调用"
IFileInfoService <|.. FileInfoServiceImpl : "实现"
FileApiImpl --> IFileInfoService : "依赖"
FileController --> KkFileViewClient : "预览"
OrphanChunkCleanupTask --> IFileInfoService : "清理"
图示来源
- FileController.java
- IFileInfoService.java
- FileInfoServiceImpl.java
- FileApiImpl.java
- KkFileViewClient.java
- OrphanChunkCleanupTask.java
章节来源
- FileController.java
- IFileInfoService.java
- FileInfoServiceImpl.java
- FileApiImpl.java
- KkFileViewClient.java
- OrphanChunkCleanupTask.java
复杂逻辑流程图(数据权限过滤)
flowchart TD
Start(["进入受控方法"]) --> CheckAnno["检查是否标注数据权限注解"]
CheckAnno --> |是| BuildScope["构建数据范围条件"]
CheckAnno --> |否| Skip["跳过数据权限过滤"]
BuildScope --> ApplyScope["应用到查询条件"]
ApplyScope --> ExecQuery["执行数据库查询"]
Skip --> ExecQuery
ExecQuery --> Return["返回受控结果"]
图示来源
- DataScope.java
- DataScopeHelper.java
- DataVisibilityContext.java
章节来源
- DataScope.java
- DataScopeHelper.java
- DataVisibilityContext.java
依赖分析
模块间依赖关系清晰,遵循“上层依赖下层”的原则:
- crm-app 依赖 crm-auth 与 crm-file
- crm-auth 与 crm-file 均依赖 crm-base
- 各模块内按 controller -> service -> mapper 分层依赖
graph LR
APP["crm-app"] --> AUTH["crm-auth"]
APP --> FILE["crm-file"]
AUTH --> BASE["crm-base"]
FILE --> BASE
图示来源
- pom.xml
章节来源
- pom.xml
性能考虑
- 分布式 ID:使用雪花算法生成唯一 ID,避免自增主键在高并发下的瓶颈
- 元数据填充:通过 MyBatis Plus 的元数据填充减少手动赋值开销
- 数据权限:尽量将数据权限条件下推到 SQL 层,减少内存过滤
- 缓存与限流:对热点数据(如部门树、菜单)考虑引入缓存;对外部调用(如第三方登录、文件预览)增加超时与重试策略
- 分页查询:合理使用分页,避免一次性加载大量数据
[本节为通用指导,不直接分析具体文件]
故障排查指南
- 全局异常处理
- 统一捕获业务异常、参数异常、权限异常与资源不存在异常
- 返回统一 Result 结构,便于前端处理
- 常见异常定位
- 参数缺失:检查 BaseParam 校验规则与入参映射
- 权限不足:检查 DataScope/DataOwnership 注解与上下文设置
- 资源不存在:检查查询条件与数据归属
- 日志追踪
- TraceIdFilter:为每个请求生成追踪 ID,贯穿日志链路
- 建议在关键路径打印必要上下文,避免泄露敏感信息
章节来源
- GlobalExceptionHandlerAdvice.java
- BusinessErrorException.java
- MissingParameterException.java
- PermissionErrorException.java
- ResourceNotExistException.java
- TraceIdFilter.java
结论
本规范从代码风格、命名约定、包结构到实体与 DTO 设计、异常与日志、Git 工作流与代码审查,提供了完整的开发标准。遵循这些规范有助于提升代码质量、降低协作成本,并为后续扩展与维护奠定基础。
附录
代码风格与命名约定
- 类名:大驼峰,名词或名词短语(如 UserService、FileInfo)
- 方法名:小驼峰,动词开头(如 getUserById、uploadFile)
- 常量:全大写加下划线(如 MAX_RETRY_COUNT)
- 包名:全小写,按功能划分(controller、service、mapper、domain、config、security、utils)
- 字段命名:小驼峰,语义明确,避免缩写歧义
包结构规范
- controller:HTTP 接口层,仅做参数校验与调用服务
- service:业务逻辑层,事务边界与方法编排
- mapper:数据访问层,基于 MyBatis Plus
- domain:
- entity:持久化实体
- dto:数据传输对象
- param:请求参数
- enums:枚举定义
- config:配置类(Spring、MyBatis Plus、Redis、Knife4j 等)
- security:安全相关(过滤器、拦截器、上下文、工具)
- utils:通用工具类
- advice:全局异常处理
- filter:过滤器(如追踪 ID)
实体类设计规范
- 所有实体继承 BaseEntity,获得审计字段
- 需要数据归属控制的实体继承 OwnedEntity
- 避免在实体中放置业务逻辑,保持 POJO 特性
- 字段注释完整,便于文档生成与理解
DTO、Param、Result 设计模式
- DTO:面向接口输出,精简字段,避免泄露内部结构
- Param:面向输入,严格校验,必要时使用分组校验
- Result/PageResult:统一响应格式,便于前端解析
- 枚举:集中定义,避免魔法值
异常处理规范
- 自定义异常分类:业务异常、参数异常、权限异常、资源不存在异常
- 全局异常处理器统一捕获并转换为 Result
- 避免吞掉异常,确保错误可追溯
日志记录规范
- 使用统一日志框架,区分 INFO/WARN/ERROR
- 关键路径记录必要上下文,避免敏感信息泄露
- 使用 TraceIdFilter 生成的追踪 ID 串联日志
注释编写规范
- 类与方法必须有清晰注释,说明职责、参数、返回值与异常
- 复杂逻辑添加行内注释,解释关键步骤
- 枚举与常量需有含义明确的描述
Git 提交信息规范
- 格式:():
- type:feat、fix、docs、style、refactor、test、chore
- scope:模块或功能范围(如 auth、file、base)
- subject:简洁明了,不超过 50 字符
分支管理策略
- main:稳定版本,仅接受合并请求
- develop:开发主干,日常集成
- feature/*:功能分支,完成后合并至 develop
- hotfix/*:热修复分支,紧急修复后合并至 main 与 develop
代码审查流程
- 提交前自检:编译通过、单元测试覆盖、符合规范
- 发起 MR/PR:填写变更说明与影响范围
- 审查要点:逻辑正确性、性能、安全性、可维护性
- 通过后合并:确保 CI 通过且无冲突