# 基础框架模块(crm-base) **本文引用的文件** - [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) - [StatusEnum.java](file://crm-base/src/main/java/com/crm/base/domain/enums/StatusEnum.java) - [HasValueEnum.java](file://crm-base/src/main/java/com/crm/base/domain/enums/HasValueEnum.java) - [CommonConstants.java](file://crm-base/src/main/java/com/crm/base/constant/CommonConstants.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java) - [CustomIdGenerator.java](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java) - [SnowflakeIdWorker.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java) - [SnowflakeProperties.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeProperties.java) - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) - [JacksonConfig.java](file://crm-base/src/main/java/com/crm/base/config/JacksonConfig.java) - [Knife4jConfig.java](file://crm-base/src/main/java/com/crm/base/config/Knife4jConfig.java) - [CorsConfig.java](file://crm-base/src/main/java/com/crm/base/config/CorsConfig.java) - [InsertBatchOnDuplicateKeyUpdate.java](file://crm-base/src/main/java/com/crm/base/config/InsertBatchOnDuplicateKeyUpdate.java) - [TraceIdFilter.java](file://crm-base/src/main/java/com/crm/base/filter/TraceIdFilter.java) - [CrmBaseMapper.java](file://crm-base/src/main/java/com/crm/base/mapper/CrmBaseMapper.java) - [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java) - [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java) - [AssertUtils.java](file://crm-base/src/main/java/com/crm/base/utils/AssertUtils.java) - [BeanCopyUtils.java](file://crm-base/src/main/java/com/crm/base/utils/BeanCopyUtils.java) - [EnumUtils.java](file://crm-base/src/main/java/com/crm/base/utils/EnumUtils.java) - [ExcelUtil.java](file://crm-base/src/main/java/com/crm/base/utils/ExcelUtil.java) - [PageConverter.java](file://crm-base/src/main/java/com/crm/base/utils/PageConverter.java) - [ServletUtils.java](file://crm-base/src/main/java/com/crm/base/utils/ServletUtils.java) - [TreeUtils.java](file://crm-base/src/main/java/com/crm/base/utils/TreeUtils.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) - [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) - [DictGroup.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroup.java) - [DictItem.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictItem.java) - [DictGroupDefault.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroupDefault.java) - [DictRefCount.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictRefCount.java) - [DictGroupVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictGroupVO.java) - [DictItemVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictItemVO.java) - [DictGroupController.java](file://crm-dict/src/main/java/com/crm/dict/controller/DictGroupController.java) - [DictItemController.java](file://crm-dict/src/main/java/com/crm/dict/controller/DictItemController.java) - [IDictGroupService.java](file://crm-dict/src/main/java/com/crm/dict/service/IDictGroupService.java) - [IDictItemService.java](file://crm-dict/src/main/java/com/crm/dict/service/IDictItemService.java) - [DictGroupServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictGroupServiceImpl.java) - [DictItemServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictItemServiceImpl.java) - [DictDataInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictDataInitializer.java) - [DictPermissionInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictPermissionInitializer.java) - [DictConstants.java](file://crm-dict/src/main/java/com/crm/dict/constant/DictConstants.java) ## 更新摘要 **变更内容** - 更新了数据字典模块的VO设计架构,DictGroupVO和DictItemVO现在使用独立字段定义而非继承实体类 - 增强了API设计的清晰度和安全性,通过明确的字段暴露控制敏感信息 - 优化了服务层实现以适配新的VO结构,提升了数据转换效率 - 完善了VO设计模式的最佳实践说明 ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考量](#性能考量) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本模块为 CRM 后端的基础设施层,提供通用实体、分页与结果封装、全局异常处理、数据访问层封装、工具类以及 MyBatis Plus、Redis、雪花ID等关键配置。通过统一的设计模式与约定,降低业务模块重复开发成本,提升一致性与可维护性。 **更新** 新增 crm-dict 数据字典模块,作为独立的服务模块提供平台级键值字典管理能力,支持分组管理、字典项管理、引用计数和权限集成等功能。该模块采用了先进的VO设计模式,通过独立的视图对象定义提升了API的安全性和清晰度。 ## 项目结构 crm-base 采用分层组织: - domain:通用实体、DTO、参数、枚举、异常、结果封装 - config:MyBatis Plus、Redis、Jackson、Knife4j、跨域、SQL注入器、填充处理器、ID生成器等 - service/mapper:通用服务接口与实现、基础 Mapper - advice/filter:全局异常处理、请求链路追踪过滤器 - security:数据权限控制、可见性上下文、登录用户模型与安全工具 - utils:通用工具集(断言、拷贝、枚举、Excel、分页转换、Servlet、树形结构) **更新** crm-dict 模块结构: - controller:字典分组和字典项的管理接口 - service:字典查询、引用计数、分组和字典项的业务逻辑 - domain:字典实体、DTO、参数定义,采用独立VO设计模式 - config:内置数据初始化、权限种子化配置 - constant:字典模块常量定义 ```mermaid graph TB subgraph "基础框架 (crm-base)" A["BaseEntity / OwnedEntity"] B["BaseDTO / BaseParam"] C["Result / PageResult / ResultCodeEnum"] D["StatusEnum / HasValueEnum"] E["MybatisPlusConfig / CrmSqlInjector"] F["RedisConfig / JacksonConfig"] G["GlobalExceptionHandlerAdvice"] H["DataScope / SecurityUtils"] end subgraph "数据字典 (crm-dict)" I["DictGroup / DictItem"] J["DictGroupVO / DictItemVO"] K["DictGroupController / DictItemController"] L["IDictGroupService / IDictItemService"] M["DictDataInitializer / DictPermissionInitializer"] N["DictConstants"] end A --> L B --> L C --> K E --> L F --> M G --> K H --> K I --> J J --> K L --> E M --> I N --> L ``` **图表来源** - [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java) - [DictGroup.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroup.java) - [DictItem.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictItem.java) - [DictGroupVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictGroupVO.java) - [DictItemVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictItemVO.java) - [DictGroupController.java](file://crm-dict/src/main/java/com/crm/dict/controller/DictGroupController.java) - [IDictGroupService.java](file://crm-dict/src/main/java/com/crm/dict/service/IDictGroupService.java) - [DictDataInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictDataInitializer.java) **章节来源** - [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java) - [DictGroup.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroup.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) ## 核心组件 - 通用实体与继承体系 - BaseEntity:定义统一的审计字段(如创建时间、更新时间、逻辑删除标记等),配合元数据填充处理器自动落库。 - OwnedEntity:在 BaseEntity 基础上扩展数据归属字段(如所属部门/租户),支撑数据权限过滤。 - 通用 DTO/Param - BaseDTO:作为对象转换的基类,便于与实体解耦。 - BaseParam:作为查询/操作参数的基类,统一分页、排序等公共字段。 - 统一结果与分页 - Result:标准响应体,包含状态码、消息与数据。 - PageResult:分页结果封装,适配 MyBatis Plus 的分页对象。 - ResultCodeEnum:统一错误码枚举。 - 枚举与常量 - StatusEnum、HasValueEnum:常用状态与布尔值语义化枚举。 - CommonConstants:系统级常量。 - 数据访问封装 - CrmBaseMapper:基础 Mapper,扩展通用方法。 - IBaseService / BaseServiceImpl:CRUD 抽象,结合分页、批量插入、更新策略等。 - 全局异常处理 - GlobalExceptionHandlerAdvice:集中捕获业务异常、参数异常、权限异常等,返回统一 Result。 - 安全与数据权限 - DataScope 注解 + DataScopeHelper:声明式数据范围控制。 - DataVisibilityContext:线程可见性上下文,存储当前用户的数据范围。 - SecurityUtils / LoginUser:获取当前登录用户信息。 - 基础设施配置 - MyBatis Plus 配置:分页插件、SQL 注入器、填充处理器、自定义 ID 生成器。 - Redis 配置:序列化、连接池、过期策略等。 - Jackson 配置:日期、空值、时区等序列化策略。 - Knife4j 配置:API 文档增强。 - CorsConfig:跨域支持。 - InsertBatchOnDuplicateKeyUpdate:批量插入去重策略。 - TraceIdFilter:请求链路追踪。 - 工具类 - AssertUtils、BeanCopyUtils、EnumUtils、ExcelUtil、PageConverter、ServletUtils、TreeUtils。 **更新** 数据字典核心组件: - 字典实体:DictGroup(分组)、DictItem(字典项)、DictGroupDefault(默认项)、DictRefCount(引用计数) - **VO设计模式**:DictGroupVO和DictItemVO采用独立字段定义,不继承实体类,提供更清晰的API契约 - 控制器:DictGroupController、DictItemController 提供 RESTful API - 服务层:IDictGroupService、IDictItemService 定义业务接口 - 初始化器:DictDataInitializer(内置数据)、DictPermissionInitializer(权限种子) - 常量定义:DictConstants 包含状态码、权限码、缓存配置等 **章节来源** - [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) - [StatusEnum.java](file://crm-base/src/main/java/com/crm/base/domain/enums/StatusEnum.java) - [HasValueEnum.java](file://crm-base/src/main/java/com/crm/base/domain/enums/HasValueEnum.java) - [CommonConstants.java](file://crm-base/src/main/java/com/crm/base/constant/CommonConstants.java) - [CrmBaseMapper.java](file://crm-base/src/main/java/com/crm/base/mapper/CrmBaseMapper.java) - [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java) - [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java) - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java) - [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) - [JacksonConfig.java](file://crm-base/src/main/java/com/crm/base/config/JacksonConfig.java) - [Knife4jConfig.java](file://crm-base/src/main/java/com/crm/base/config/Knife4jConfig.java) - [CorsConfig.java](file://crm-base/src/main/java/com/crm/base/config/CorsConfig.java) - [InsertBatchOnDuplicateKeyUpdate.java](file://crm-base/src/main/java/com/crm/base/config/InsertBatchOnDuplicateKeyUpdate.java) - [TraceIdFilter.java](file://crm-base/src/main/java/com/crm/base/filter/TraceIdFilter.java) - [AssertUtils.java](file://crm-base/src/main/java/com/crm/base/utils/AssertUtils.java) - [BeanCopyUtils.java](file://crm-base/src/main/java/com/crm/base/utils/BeanCopyUtils.java) - [EnumUtils.java](file://crm-base/src/main/java/com/crm/base/utils/EnumUtils.java) - [ExcelUtil.java](file://crm-base/src/main/java/com/crm/base/utils/ExcelUtil.java) - [PageConverter.java](file://crm-base/src/main/java/com/crm/base/utils/PageConverter.java) - [ServletUtils.java](file://crm-base/src/main/java/com/crm/base/utils/ServletUtils.java) - [TreeUtils.java](file://crm-base/src/main/java/com/crm/base/utils/TreeUtils.java) - [DictGroup.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroup.java) - [DictItem.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictItem.java) - [DictGroupDefault.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroupDefault.java) - [DictRefCount.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictRefCount.java) - [DictGroupVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictGroupVO.java) - [DictItemVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictItemVO.java) - [DictGroupController.java](file://crm-dict/src/main/java/com/crm/dict/controller/DictGroupController.java) - [DictItemController.java](file://crm-dict/src/main/java/com/crm/dict/controller/DictItemController.java) - [IDictGroupService.java](file://crm-dict/src/main/java/com/crm/dict/service/IDictGroupService.java) - [IDictItemService.java](file://crm-dict/src/main/java/com/crm/dict/service/IDictItemService.java) - [DictGroupServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictGroupServiceImpl.java) - [DictItemServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictItemServiceImpl.java) - [DictDataInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictDataInitializer.java) - [DictPermissionInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictPermissionInitializer.java) - [DictConstants.java](file://crm-dict/src/main/java/com/crm/dict/constant/DictConstants.java) ## 架构总览 基础框架围绕"实体-服务-Mapper"三层展开,辅以配置中心与横切能力: - 实体层:BaseEntity/OwnedEntity 提供统一字段与审计;OwnedEntity 承载数据归属。 - 服务层:IBaseService/BaseServiceImpl 提供 CRUD、分页、批量操作与事务边界。 - 数据层:CrmBaseMapper 扩展通用 SQL;MyBatis Plus 插件负责分页、填充、ID 生成。 - 横切:全局异常、数据权限、请求追踪、序列化、缓存、API 文档、跨域。 **更新** 新增 crm-dict 模块架构: - 独立服务模块:基于 crm-base 构建,不依赖 crm-auth 具体实现 - 两级字典结构:分组 → 字典项,支持内置和用户字典分离 - **VO设计模式**:采用独立的视图对象(DictGroupVO、DictItemVO)替代实体继承,提升API安全性和清晰度 - 引用计数机制:跟踪字典项使用情况,防止误删 - 权限集成:通过权限码契约与 crm-auth 解耦集成 - 本地缓存:使用 Caffeine 提供高性能字典查询缓存 ```mermaid classDiagram class BaseEntity { +id +createTime +updateTime +deleted } class OwnedEntity { +ownerId +deptId } class DictGroup { +code +name +status +builtin +deleteKey } class DictItem { +groupId +code +name +value +status +builtin +deleteKey } class DictGroupVO { +id +name +code +sortNo +status +description +builtin +createTime +itemCount } class DictItemVO { +id +groupId +name +code +value +sortNo +status +description +builtin +createTime +groupName +isDefault +referenced +effectiveSelectable } class DictGroupDefault { +groupId +itemId } class DictRefCount { +groupCode +itemCode +refCount } class IBaseService~T~ { +save(entity) +updateById(entity) +removeById(id) +getById(id) +list(param) +page(param) +batchSave(list) } class IDictGroupService { +pageGroups(param) +saveGroup(group) +deleteGroup(id) +updateGroupStatus(id, status) +listEnabled() } class IDictItemService { +pageItems(param) +saveItem(item) +deleteItem(id) +forceDeleteItem(id) +updateItemStatus(id, status) +setDefault(groupId, itemId) } class DictDataInitializer class DictPermissionInitializer OwnedEntity --|> BaseEntity DictGroup --> DictGroupDefault : "一对多" DictItem --> DictRefCount : "引用计数" IDictGroupService --> IBaseService : "继承" IDictItemService --> IBaseService : "继承" DictDataInitializer --> DictGroup : "初始化" DictDataInitializer --> DictItem : "初始化" DictPermissionInitializer --> DictGroup : "权限绑定" ``` **图表来源** - [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) - [DictGroup.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroup.java) - [DictItem.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictItem.java) - [DictGroupVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictGroupVO.java) - [DictItemVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictItemVO.java) - [DictGroupDefault.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroupDefault.java) - [DictRefCount.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictRefCount.java) - [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java) - [IDictGroupService.java](file://crm-dict/src/main/java/com/crm/dict/service/IDictGroupService.java) - [IDictItemService.java](file://crm-dict/src/main/java/com/crm/dict/service/IDictItemService.java) - [DictDataInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictDataInitializer.java) - [DictPermissionInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictPermissionInitializer.java) ## 详细组件分析 ### 通用实体与数据归属 - BaseEntity 提供统一审计字段,配合 MetaObjectFillHandler 自动填充创建/更新时间、操作人等。 - OwnedEntity 扩展数据归属字段,用于数据权限过滤(如按部门/租户隔离)。 - 建议所有业务实体继承 OwnedEntity,确保数据权限生效。 ```mermaid classDiagram class BaseEntity { +id +createTime +updateTime +deleted } class OwnedEntity { +ownerId +deptId } OwnedEntity --|> BaseEntity ``` **图表来源** - [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) **章节来源** - [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) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java) ### 分页与结果封装 - PageResult 封装分页数据,适配 MyBatis Plus 的分页对象,提供 total/pages/current/size/records。 - Result 统一响应格式,ResultCodeEnum 统一定义状态码。 - PageConverter 提供将业务分页对象转换为 PageResult 的工具方法。 ```mermaid flowchart TD Start(["进入分页查询"]) --> BuildParam["构建查询参数(BaseParam)"] BuildParam --> QueryDB["调用 Service.page()"] QueryDB --> Convert["PageConverter 转换"] Convert --> Wrap["包装为 PageResult"] Wrap --> Return["返回 Result.success(PageResult)"] ``` **图表来源** - [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java) - [PageConverter.java](file://crm-base/src/main/java/com/crm/base/utils/PageConverter.java) - [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java) - [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java) **章节来源** - [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.java) - [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java) - [PageConverter.java](file://crm-base/src/main/java/com/crm/base/utils/PageConverter.java) ### 数据访问层封装与 CRUD - CrmBaseMapper:基础 Mapper,扩展通用方法,减少样板代码。 - IBaseService/BaseServiceImpl:提供 save/update/remove/get/list/page/batchSave 等通用方法,内部集成分页、填充、ID 生成与事务管理。 - 批量插入策略:InsertBatchOnDuplicateKeyUpdate 提供幂等写入能力。 ```mermaid sequenceDiagram participant C as "Controller" participant S as "BaseServiceImpl" participant M as "CrmBaseMapper" participant MP as "MyBatis Plus" C->>S : "page(BaseParam)" S->>MP : "构造分页查询(含数据权限)" MP->>M : "执行 SQL" M-->>MP : "返回记录集" MP-->>S : "分页对象" S-->>C : "PageResult" ``` **图表来源** - [CrmBaseMapper.java](file://crm-base/src/main/java/com/crm/base/mapper/CrmBaseMapper.java) - [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java) - [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) **章节来源** - [CrmBaseMapper.java](file://crm-base/src/main/java/com/crm/base/mapper/CrmBaseMapper.java) - [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java) - [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java) - [InsertBatchOnDuplicateKeyUpdate.java](file://crm-base/src/main/java/com/crm/base/config/InsertBatchOnDuplicateKeyUpdate.java) ### 全局异常处理机制 - GlobalExceptionHandlerAdvice 集中捕获业务异常、参数缺失、权限错误、资源不存在等,统一返回 Result。 - 自定义异常类型:BusinessErrorException、MissingParameterException、PermissionErrorException、ResourceNotExistException。 - 建议业务层抛出明确异常,由该拦截器统一收敛。 ```mermaid flowchart TD Entry(["请求进入"]) --> TryBlock["执行业务逻辑"] TryBlock --> Success{"是否成功?"} Success --> |是| Ok["返回 Result.success(data)"] Success --> |否| Catch["捕获特定异常"] Catch --> Map["映射为 Result.error(code,message)"] Map --> End(["返回统一响应"]) ``` **图表来源** - [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) - [Result.java](file://crm-base/src/main/java/com/crm/base/domain/result/Result.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 注解:标注在方法或类上,声明数据范围级别。 - DataScopeHelper:解析注解并组装 WHERE 条件(如 deptId/ownerId)。 - DataVisibilityContext:线程内保存当前用户的数据可见范围。 - SecurityUtils/LoginUser:从上下文获取当前登录用户信息。 ```mermaid sequenceDiagram participant U as "调用方" participant S as "Service方法" participant DS as "DataScopeHelper" participant CTX as "DataVisibilityContext" U->>S : "带@DataScope的方法调用" S->>DS : "解析注解与用户范围" DS->>CTX : "设置可见范围" DS-->>S : "返回过滤条件片段" S-->>U : "返回受限数据集合" ``` **图表来源** - [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java) - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java) - [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java) **章节来源** - [DataScope.java](file://crm-base/src/main/java/com/crm/base/annotation/DataScope.java) - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [SecurityUtils.java](file://crm-base/src/main/java/com/crm/base/security/SecurityUtils.java) - [LoginUser.java](file://crm-base/src/main/java/com/crm/base/security/LoginUser.java) ### MyBatis Plus 配置与扩展 - MybatisPlusConfig:注册分页插件、SQL 注入器、填充处理器、自定义 ID 生成器。 - CrmSqlInjector:扩展通用 SQL 片段与方法。 - MetaObjectFillHandler:自动填充审计字段(创建时间、更新时间、操作人等)。 - CustomIdGenerator:基于 SnowflakeIdWorker 生成分布式唯一 ID。 - SnowflakeProperties:雪花算法相关配置(工作节点、数据中心等)。 ```mermaid flowchart TD Init["应用启动"] --> Register["注册 MyBatis Plus 插件"] Register --> Fill["注册 MetaObjectFillHandler"] Register --> Inject["注册 CrmSqlInjector"] Register --> IdGen["注册 CustomIdGenerator"] IdGen --> Snow["SnowflakeIdWorker 生成ID"] Fill --> Audit["自动填充审计字段"] Inject --> SQL["扩展通用 SQL"] ``` **图表来源** - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java) - [CustomIdGenerator.java](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java) - [SnowflakeIdWorker.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java) - [SnowflakeProperties.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeProperties.java) **章节来源** - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [CrmSqlInjector.java](file://crm-base/src/main/java/com/crm/base/config/CrmSqlInjector.java) - [MetaObjectFillHandler.java](file://crm-base/src/main/java/com/crm/base/config/MetaObjectFillHandler.java) - [CustomIdGenerator.java](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java) - [SnowflakeIdWorker.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java) - [SnowflakeProperties.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeProperties.java) ### Redis 集成与缓存配置 - RedisConfig:配置序列化、连接池、默认过期策略等,供业务模块按需使用。 - 建议对热点数据(字典、菜单树、权限等)进行缓存,注意一致性策略与失效时机。 ```mermaid flowchart TD App["应用启动"] --> RConf["初始化 RedisConfig"] RConf --> Serializer["配置序列化器"] RConf --> Pool["配置连接池"] RConf --> TTL["设置默认过期策略"] App --> Use["业务模块使用 RedisTemplate"] ``` **图表来源** - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) **章节来源** - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) ### Jackson 与 API 文档、跨域 - JacksonConfig:统一日期格式、时区、空值序列化策略。 - Knife4jConfig:增强 Swagger 文档体验。 - CorsConfig:允许跨域访问,便于前后端分离开发。 **章节来源** - [JacksonConfig.java](file://crm-base/src/main/java/com/crm/base/config/JacksonConfig.java) - [Knife4jConfig.java](file://crm-base/src/main/java/com/crm/base/config/Knife4jConfig.java) - [CorsConfig.java](file://crm-base/src/main/java/com/crm/base/config/CorsConfig.java) ### 工具类与辅助能力 - AssertUtils:参数校验与断言。 - BeanCopyUtils:对象属性拷贝。 - EnumUtils:枚举工具方法。 - ExcelUtil:导入导出 Excel。 - PageConverter:分页对象转换。 - ServletUtils:HTTP 请求辅助。 - TreeUtils:树形结构构建。 **章节来源** - [AssertUtils.java](file://crm-base/src/main/java/com/crm/base/utils/AssertUtils.java) - [BeanCopyUtils.java](file://crm-base/src/main/java/com/crm/base/utils/BeanCopyUtils.java) - [EnumUtils.java](file://crm-base/src/main/java/com/crm/base/utils/EnumUtils.java) - [ExcelUtil.java](file://crm-base/src/main/java/com/crm/base/utils/ExcelUtil.java) - [PageConverter.java](file://crm-base/src/main/java/com/crm/base/utils/PageConverter.java) - [ServletUtils.java](file://crm-base/src/main/java/com/crm/base/utils/ServletUtils.java) - [TreeUtils.java](file://crm-base/src/main/java/com/crm/base/utils/TreeUtils.java) ### 数据字典模块详解 #### VO设计模式重构 **更新** 数据字典模块采用了先进的VO设计模式,DictGroupVO和DictItemVO现在使用独立的字段定义而非继承实体类,显著提升了API设计的清晰度和安全性。 - **DictGroupVO**:专门用于分页列表展示的视图对象,只暴露前端需要的业务字段(id、name、code、sortNo、status、description、builtin、createTime、itemCount),排除了敏感的审计字段(creatorId/updaterId/updateTime/deleted)和软删内部字段(deleteKey)。 - **DictItemVO**:字典项视图对象,包含丰富的展示字段(groupName、isDefault、referenced、effectiveSelectable),其中referenced字段实时读取引用计数,绝不进缓存,确保数据准确性。 ```mermaid classDiagram class BaseEntity { +id +createTime +updateTime +deleted } class DictGroup { +code +name +status +builtin +deleteKey } class DictItem { +groupId +code +name +value +status +builtin +deleteKey } class DictGroupVO { +id +name +code +sortNo +status +description +builtin +createTime +itemCount } class DictItemVO { +id +groupId +name +code +value +sortNo +status +description +builtin +createTime +groupName +isDefault +referenced +effectiveSelectable } DictGroup --> DictGroupVO : "toDTO()" DictItem --> DictItemVO : "toDTO()" ``` **图表来源** - [BaseEntity.java](file://crm-base/src/main/java/com/crm/base/domain/entity/BaseEntity.java) - [DictGroup.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroup.java) - [DictItem.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictItem.java) - [DictGroupVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictGroupVO.java) - [DictItemVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictItemVO.java) #### 核心实体设计 - **DictGroup(字典分组)**:字典的第一级容器,具有全局唯一编码,创建后不可修改。支持内置标记区分平台内置和用户自定义字典。 - **DictItem(字典项)**:字典的第二级键值条目,身份由{分组ID, 编码}确定,创建后不可修改。支持字典值同组唯一约束。 - **DictGroupDefault(分组默认项)**:通过主键约束保证每组最多一个默认项,独立表存储避免污染字典项实体。 - **DictRefCount(引用计数)**:跟踪字典项被业务数据引用的次数,防止误删已使用的字典项。 ```mermaid classDiagram class DictGroup { +Long id +String code +String name +Integer sortNo +Integer status +Boolean builtin +Long deleteKey } class DictItem { +Long id +Long groupId +String code +String name +String value +Integer sortNo +Integer status +Boolean builtin +Long deleteKey } class DictGroupDefault { +Long groupId +Long itemId } class DictRefCount { +String groupCode +String itemCode +Integer refCount } DictGroup "1" --> "0..*" DictItem : "拥有" DictGroup "1" --> "0..1" DictGroupDefault : "默认项" DictItem "1" --> "0..1" DictRefCount : "引用计数" ``` **图表来源** - [DictGroup.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroup.java) - [DictItem.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictItem.java) - [DictGroupDefault.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroupDefault.java) - [DictRefCount.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictRefCount.java) #### 控制器与服务层 - **DictGroupController**:提供分组管理的 RESTful API,包括分页查询、新建编辑、删除、启停等操作。 - **DictItemController**:提供字典项管理的 RESTful API,支持分页查询、CRUD、默认项设置、强制删除等功能。 - **IDictGroupService/IDictItemService**:定义业务接口,继承 IBaseService 获得通用 CRUD 能力。 - **DictGroupServiceImpl**:实现分组业务逻辑,包含数据验证、权限检查、事务管理等。 ```mermaid sequenceDiagram participant Client as "客户端" participant Controller as "DictGroupController" participant Service as "IDictGroupService" participant DB as "数据库" Client->>Controller : POST /api/dict/group/saveOrUpdate Controller->>Service : saveGroup(DictGroup) Service->>Service : 数据验证与权限检查 Service->>DB : INSERT/UPDATE dict_group DB-->>Service : 操作结果 Service-->>Controller : 业务结果 Controller-->>Client : Result.success() ``` **图表来源** - [DictGroupController.java](file://crm-dict/src/main/java/com/crm/dict/controller/DictGroupController.java) - [IDictGroupService.java](file://crm-dict/src/main/java/com/crm/dict/service/IDictGroupService.java) - [DictGroupServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictGroupServiceImpl.java) #### 初始化与权限集成 - **DictDataInitializer**:应用启动时执行内置字典的幂等初始化,支持 Excel 替换口,保护用户字典不被覆盖。 - **DictPermissionInitializer**:权限种子化,将 10 个 dict:* 权限点注入到权限资源树,并与管理员角色绑定。 - **DictConstants**:集中定义状态码、权限码、缓存配置、错误码等常量。 ```mermaid flowchart TD Startup["应用启动"] --> DataInit["DictDataInitializer.run()"] Startup --> PermInit["DictPermissionInitializer.run()"] DataInit --> Validate["校验种子数据"] Validate --> UpsertGroup["upsertGroup()"] UpsertGroup --> UpsertItem["upsertItem()"] UpsertItem --> SetDefault["setDefaultIfAbsent()"] PermInit --> CreateMenu["创建菜单节点"] CreateMenu --> CreateButtons["创建权限按钮"] CreateButtons --> BindRole["绑定管理员角色"] ``` **图表来源** - [DictDataInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictDataInitializer.java) - [DictPermissionInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictPermissionInitializer.java) - [DictConstants.java](file://crm-dict/src/main/java/com/crm/dict/constant/DictConstants.java) **章节来源** - [DictGroup.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroup.java) - [DictItem.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictItem.java) - [DictGroupDefault.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictGroupDefault.java) - [DictRefCount.java](file://crm-dict/src/main/java/com/crm/dict/domain/entity/DictRefCount.java) - [DictGroupVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictGroupVO.java) - [DictItemVO.java](file://crm-dict/src/main/java/com/crm/dict/domain/dto/DictItemVO.java) - [DictGroupController.java](file://crm-dict/src/main/java/com/crm/dict/controller/DictGroupController.java) - [DictItemController.java](file://crm-dict/src/main/java/com/crm/dict/controller/DictItemController.java) - [IDictGroupService.java](file://crm-dict/src/main/java/com/crm/dict/service/IDictGroupService.java) - [IDictItemService.java](file://crm-dict/src/main/java/com/crm/dict/service/IDictItemService.java) - [DictGroupServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictGroupServiceImpl.java) - [DictItemServiceImpl.java](file://crm-dict/src/main/java/com/crm/dict/service/impl/DictItemServiceImpl.java) - [DictDataInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictDataInitializer.java) - [DictPermissionInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictPermissionInitializer.java) - [DictConstants.java](file://crm-dict/src/main/java/com/crm/dict/constant/DictConstants.java) ## 依赖关系分析 - 实体与服务:BaseEntity/OwnedEntity 被 BaseServiceImpl 广泛使用;IBaseService 定义契约。 - 数据访问:CrmBaseMapper 被 BaseServiceImpl 依赖;MyBatis Plus 插件贯穿整个数据层。 - 横切:GlobalExceptionHandlerAdvice 作用于所有 Controller;DataScopeHelper 与 DataVisibilityContext 影响查询条件。 - 外部依赖:Redis 用于缓存;Jackson 用于序列化;Knife4j 用于文档;Cors 用于跨域。 **更新** 新增 crm-dict 模块依赖关系: - crm-dict 仅依赖 crm-base,不直接依赖 crm-auth,通过权限码契约解耦 - 使用 Caffeine 本地缓存提升字典查询性能 - 通过 CommandLineRunner 实现启动时初始化 - 与 crm-auth 通过权限资源树间接集成 - **VO设计模式**:通过独立的视图对象减少了实体与API的直接耦合 ```mermaid graph LR Entity["BaseEntity/OwnedEntity"] --> Service["IBaseService/BaseServiceImpl"] Service --> Mapper["CrmBaseMapper"] Service --> MP["MyBatisPlusConfig"] MP --> Fill["MetaObjectFillHandler"] MP --> ID["CustomIdGenerator/SnowflakeIdWorker"] Service --> Cache["RedisConfig"] Controller["业务Controller"] --> Service Controller --> Exception["GlobalExceptionHandlerAdvice"] Service --> Scope["DataScopeHelper/DataVisibilityContext"] DictModule["crm-dict 模块"] --> BaseModule["crm-base 模块"] DictModule --> Caffeine["Caffeine 缓存"] DictModule --> AuthContract["权限码契约"] AuthContract --> AuthModule["crm-auth 模块"] DictModule --> VOPattern["VO设计模式"] VOPattern --> APIClear["清晰的API契约"] ``` **图表来源** - [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) - [IBaseService.java](file://crm-base/src/main/java/com/crm/base/service/IBaseService.java) - [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java) - [CrmBaseMapper.java](file://crm-base/src/main/java/com/crm/base/mapper/CrmBaseMapper.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) - [CustomIdGenerator.java](file://crm-base/src/main/java/com/crm/base/config/CustomIdGenerator.java) - [SnowflakeIdWorker.java](file://crm-base/src/main/java/com/crm/base/config/SnowflakeIdWorker.java) - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.java) - [DataVisibilityContext.java](file://crm-base/src/main/java/com/crm/base/security/DataVisibilityContext.java) - [pom.xml](file://crm-dict/pom.xml) **章节来源** - [BaseServiceImpl.java](file://crm-base/src/main/java/com/crm/base/service/impl/BaseServiceImpl.java) - [MybatisPlusConfig.java](file://crm-base/src/main/java/com/crm/base/config/MybatisPlusConfig.java) - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [pom.xml](file://crm-dict/pom.xml) ## 性能考量 - 分页查询:优先使用 MyBatis Plus 分页插件,避免全表扫描;合理设计索引。 - 批量操作:使用 batchSave 与 InsertBatchOnDuplicateKeyUpdate 提升写入吞吐。 - 缓存策略:对热点数据启用 Redis 缓存,设置合理 TTL 与失效策略。 - 序列化:Jackson 配置统一时区与空值策略,减少序列化开销。 - 审计填充:MetaObjectFillHandler 仅在必要时填充,避免多余数据库写操作。 **更新** 数据字典性能优化: - 使用 Caffeine 本地缓存提供 10s TTL 的字典查询缓存 - 空结果缓存 2s 防穿透,避免缓存击穿 - 引用计数表不缓存,保证数据一致性 - 聚合查询优化:分组分页时一次性查询字典项数量 - 默认排序优化:sort_no IS NULL, sort_no ASC, create_time ASC - **VO设计优化**:通过独立的VO对象减少数据传输量,提升网络传输效率 [本节为通用指导,不直接分析具体文件] ## 故障排查指南 - 统一异常:检查 GlobalExceptionHandlerAdvice 是否捕获到预期异常类型,确认 ResultCodeEnum 的状态码与消息。 - 数据权限:确认 DataScope 注解是否正确标注,DataVisibilityContext 中可见范围是否设置正确。 - 填充失败:检查 MetaObjectFillHandler 是否注册,实体字段名是否与填充规则匹配。 - ID 冲突:核对 SnowflakeIdWorker 配置(工作节点/数据中心)是否唯一,避免 ID 碰撞。 - 缓存问题:检查 Redis 连接与序列化配置,确认 key 命名规范与过期策略。 - 跨域与文档:验证 CorsConfig 与 Knife4jConfig 配置是否符合前端需求。 **更新** 数据字典故障排查: - 初始化失败:检查 DictDataInitializer 的种子数据合法性,确认 fail-fast 机制 - 权限问题:验证 DictPermissionInitializer 是否正确创建菜单和权限点 - 缓存不一致:检查 Caffeine 缓存配置,确认 TTL 设置合理 - 引用计数异常:监控 DictRefCount 表的计数准确性,必要时使用强制删除功能 - 内置字典保护:确认 builtin=true 的字典项无法被删除或修改关键字段 - **VO设计问题**:检查DictGroupVO和DictItemVO的字段映射是否正确,确保toDTO方法正常工作 **章节来源** - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [DataScopeHelper.java](file://crm-base/src/main/java/com/crm/base/security/DataScopeHelper.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) - [RedisConfig.java](file://crm-base/src/main/java/com/crm/base/config/RedisConfig.java) - [CorsConfig.java](file://crm-base/src/main/java/com/crm/base/config/CorsConfig.java) - [Knife4jConfig.java](file://crm-base/src/main/java/com/crm/base/config/Knife4jConfig.java) - [DictDataInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictDataInitializer.java) - [DictPermissionInitializer.java](file://crm-dict/src/main/java/com/crm/dict/config/DictPermissionInitializer.java) ## 结论 crm-base 提供了完善的基础设施能力,涵盖实体设计、CRUD 封装、分页与结果统一、全局异常、数据权限、MyBatis Plus 扩展、Redis 缓存、雪花 ID 生成等。遵循本模块约定,可显著提升业务模块的开发效率与一致性。 **更新** 新增 crm-dict 数据字典模块作为独立的基础设施服务,提供平台级的键值字典管理能力。该模块通过先进的VO设计模式重构,实现了更清晰的API契约和更高的安全性,同时通过解耦设计与权限码契约,实现了与认证模块的松耦合集成。VO设计模式的采用使得数据展示更加灵活可控,有效避免了敏感信息的泄露风险。 [本节为总结性内容,不直接分析具体文件] ## 附录 ### 最佳实践 - 实体设计 - 所有业务实体继承 OwnedEntity,确保数据权限生效。 - 合理使用审计字段,避免频繁手动更新 createTime/updateTime。 - 服务层 - 优先使用 IBaseService 提供的通用方法,减少样板代码。 - 复杂查询通过 CrmBaseMapper 扩展 SQL,保持可读性。 - 异常处理 - 业务层抛出明确的自定义异常,交由 GlobalExceptionHandlerAdvice 统一处理。 - 数据权限 - 在需要数据隔离的方法上使用 @DataScope,并通过 DataVisibilityContext 设置可见范围。 - 缓存 - 对热点数据使用 Redis 缓存,设置合理的 TTL 与失效策略,保证一致性。 - 工具类 - 使用 AssertUtils 做前置校验;使用 BeanCopyUtils 进行对象转换;使用 PageConverter 转换分页对象。 **更新** 数据字典最佳实践: - 字典设计:优先使用内置字典,用户字典用于个性化需求 - 编码规范:字典编码使用有意义的英文标识,避免使用数字 ID - 引用管理:业务代码中正确使用引用计数增减,避免内存泄漏 - 缓存策略:利用 Caffeine 本地缓存提升查询性能,注意缓存失效时机 - 权限控制:通过权限码进行细粒度控制,避免硬编码权限判断 - **VO设计模式**:采用独立的视图对象定义API契约,避免直接暴露实体字段,提升安全性和灵活性 [本节为通用指导,不直接分析具体文件] ### 扩展开发指南 - 新增实体 - 继承 OwnedEntity,定义必要字段;如需自定义 ID 生成策略,可在 CustomIdGenerator 中扩展。 - 新增服务方法 - 在 IBaseService 中定义接口,在 BaseServiceImpl 中实现;复杂 SQL 通过 CrmBaseMapper 扩展。 - 新增数据权限级别 - 在 DataScopeLevel 中扩展级别,并在 DataScopeHelper 中实现对应过滤逻辑。 - 新增缓存键与策略 - 在业务模块中定义缓存 Key 前缀与过期时间,使用 RedisTemplate 进行操作。 - 新增全局异常类型 - 定义新的异常类,并在 GlobalExceptionHandlerAdvice 中添加对应的处理分支。 **更新** 数据字典扩展指南: - 新增字典分组:通过 DictGroupController 的 saveOrUpdate 接口创建新分组 - 新增字典项:使用 DictItemController 的 saveOrUpdate 接口添加字典项 - 扩展内置数据:修改 DictDataInitializer 中的 SEED_GROUPS 列表 - 新增权限点:在 DictPermissionInitializer 中添加新的权限点种子 - 自定义缓存策略:扩展 DictConstants 中的缓存配置参数 - **VO扩展**:如需新增展示字段,应在DictGroupVO和DictItemVO中定义独立字段,而非修改实体类 [本节为通用指导,不直接分析具体文件]