# 领域模型 **本文引用的文件** - [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) - [BeanCopyUtils.java](file://crm-base/src/main/java/com/crm/base/utils/BeanCopyUtils.java) - [PageConverter.java](file://crm-base/src/main/java/com/crm/base/utils/PageConverter.java) - [AssertUtils.java](file://crm-base/src/main/java/com/crm/base/utils/AssertUtils.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) - [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) - [LoginParam.java](file://crm-auth/src/main/java/com/crm/auth/domain/param/LoginParam.java) - [UserInfoDTO.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/UserInfoDTO.java) - [MenuType.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/MenuType.java) - [ResourceNode.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/ResourceNode.java) - [ResourceServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/ResourceServiceImpl.java) ## 更新摘要 **所做更改** - 更新了菜单类型定义部分,反映移除了冗余的MenuTypeEnum枚举,统一使用MenuType作为节点类型定义的唯一来源 - 新增了MenuType枚举的详细分析,包括其设计模式和层级约束逻辑 - 更新了ResourceNode DTO中MenuType的使用示例 - 增强了领域模型扩展指导中关于枚举设计的最佳实践 ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考虑](#性能考虑) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本文件面向领域模型与数据契约,系统性说明 BaseDTO、BaseParam 的基类设计与继承关系,统一响应 Result 与分页结果 PageResult 的结构与用法,阐述 DTO 与 Param 的设计原则、字段验证规则与转换策略,并给出领域模型的扩展指导与自定义数据对象的创建规范。目标是帮助开发者在 CRM 后端项目中以一致、可维护的方式定义数据传输对象、参数对象以及统一的接口响应格式。 ## 项目结构 本项目采用多模块组织,领域模型相关的基础类型集中在 crm-base 模块中,业务模块(如 crm-auth)通过引入基础模块复用这些通用能力。关键位置如下: - 基础 DTO 与 Param:crm-base/domain/{dto,param} - 统一响应封装:crm-base/domain/result - 工具与转换器:crm-base/utils - 异常与全局处理:crm-base/advice 与 crm-base/domain/exception - 实体基类:crm-base/domain/entity - 业务枚举定义:crm-auth/domain/enums ```mermaid graph TB subgraph "基础模块 crm-base" A["domain/dto/BaseDTO"] B["domain/param/BaseParam"] C["domain/result/Result"] D["domain/result/PageResult"] E["utils/BeanCopyUtils"] F["utils/PageConverter"] G["advice/GlobalExceptionHandlerAdvice"] H["domain/entity/BaseEntity"] I["domain/entity/OwnedEntity"] end subgraph "业务模块 crm-auth" J["domain/param/LoginParam"] K["domain/dto/UserInfoDTO"] L["domain/enums/MenuType"] M["domain/dto/ResourceNode"] N["service/impl/ResourceServiceImpl"] end A --> C B --> C D --> C E --> A E --> B F --> D G --> C H --> I J --> B K --> A L --> M M --> N ``` 图表来源 - [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) - [BeanCopyUtils.java](file://crm-base/src/main/java/com/crm/base/utils/BeanCopyUtils.java) - [PageConverter.java](file://crm-base/src/main/java/com/crm/base/utils/PageConverter.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.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) - [LoginParam.java](file://crm-auth/src/main/java/com/crm/auth/domain/param/LoginParam.java) - [UserInfoDTO.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/UserInfoDTO.java) - [MenuType.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/MenuType.java) - [ResourceNode.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/ResourceNode.java) - [ResourceServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/ResourceServiceImpl.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) - [BeanCopyUtils.java](file://crm-base/src/main/java/com/crm/base/utils/BeanCopyUtils.java) - [PageConverter.java](file://crm-base/src/main/java/com/crm/base/utils/PageConverter.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.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) - [LoginParam.java](file://crm-auth/src/main/java/com/crm/auth/domain/param/LoginParam.java) - [UserInfoDTO.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/UserInfoDTO.java) - [MenuType.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/MenuType.java) - [ResourceNode.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/ResourceNode.java) - [ResourceServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/ResourceServiceImpl.java) ## 核心组件 - BaseDTO:所有数据传输对象的基类,提供统一的序列化、审计或扩展字段约定,便于跨层传递数据。 - BaseParam:所有请求参数的基类,集中承载校验注解、分页与排序等通用能力,简化 Controller 入参定义。 - Result:统一响应封装,包含状态码、消息与数据体,确保前后端交互一致性。 - PageResult:分页结果封装,聚合页码、总数、列表数据等分页元信息。 - BeanCopyUtils:对象拷贝工具,用于 DTO/Param/Entity 之间的属性映射与转换。 - PageConverter:分页转换工具,将框架分页对象转换为 PageResult。 - AssertUtils:断言工具,用于快速进行参数合法性校验。 - GlobalExceptionHandlerAdvice:全局异常处理器,将业务异常转换为统一 Result。 - MenuType:权限资源树节点类型枚举,定义了CATALOG、MENU、BUTTON三种节点类型及其层级约束。 章节来源 - [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) - [BeanCopyUtils.java](file://crm-base/src/main/java/com/crm/base/utils/BeanCopyUtils.java) - [PageConverter.java](file://crm-base/src/main/java/com/crm/base/utils/PageConverter.java) - [AssertUtils.java](file://crm-base/src/main/java/com/crm/base/utils/AssertUtils.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [MenuType.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/MenuType.java) ## 架构总览 下图展示了领域模型在请求链路中的角色与交互:Controller 接收 BaseParam 派生参数,经服务层处理返回 Result 或 PageResult;DTO 作为跨层数据载体,通过 BeanCopyUtils 与 Entity 相互转换。 ```mermaid sequenceDiagram participant Client as "客户端" participant Controller as "控制器" participant Service as "服务层" participant Utils as "工具类" participant Response as "统一响应" Client->>Controller : "HTTP 请求(BaseParam)" Controller->>Controller : "参数校验(注解/断言)" Controller->>Service : "调用业务方法" Service->>Utils : "对象转换(BeanCopyUtils)" Service-->>Controller : "业务结果(DTO/Entity)" Controller->>Response : "封装为Result/PageResult" Response-->>Client : "JSON 响应" ``` 图表来源 - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.java) - [BeanCopyUtils.java](file://crm-base/src/main/java/com/crm/base/utils/BeanCopyUtils.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) ## 详细组件分析 ### BaseDTO 与 BaseParam 基类设计 - BaseDTO - 职责:作为数据传输对象的基类,统一序列化行为与扩展点,避免在各 DTO 中重复定义公共字段。 - 设计要点:仅暴露必要字段,保持不可变或最小可变性;避免携带持久化细节。 - BaseParam - 职责:作为请求参数的基类,集中声明校验注解、分页与排序等通用能力。 - 设计要点:与 Controller 入参解耦,便于单元测试与 Mock;支持可选字段与默认值。 ```mermaid classDiagram class BaseDTO { + "公共字段与行为" } class BaseParam { + "公共字段与行为" } class UserInfoDTO class LoginParam UserInfoDTO --|> BaseDTO : "继承" LoginParam --|> BaseParam : "继承" ``` 图表来源 - [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) - [UserInfoDTO.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/UserInfoDTO.java) - [LoginParam.java](file://crm-auth/src/main/java/com/crm/auth/domain/param/LoginParam.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) - [UserInfoDTO.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/UserInfoDTO.java) - [LoginParam.java](file://crm-auth/src/main/java/com/crm/auth/domain/param/LoginParam.java) ### MenuType 枚举设计模式 **已更新** 移除了冗余的MenuTypeEnum枚举,统一使用MenuType作为节点类型定义的唯一来源。 - MenuType - 职责:定义权限资源树的节点类型,包含CATALOG(菜单分组)、MENU(菜单页面)、BUTTON(按钮/权限点)三种类型。 - 设计要点:提供fromCode工厂方法进行DB值到枚举的转换,isLegalChild方法实现层级约束验证。 - 层级约束:CATALOG只能包含MENU,MENU只能包含BUTTON,BUTTON是叶子节点。 ```mermaid classDiagram class MenuType { + "CATALOG : 菜单分组" + "MENU : 菜单页面" + "BUTTON : 按钮/权限点" + "fromCode(Integer) : MenuType" + "isLegalChild(MenuType, MenuType) : boolean" } class ResourceNode { + "type : MenuType" + "fromEntity(SysMenu) : ResourceNode" + "toEntity() : SysMenu" } MenuType <.. ResourceNode : "使用" ``` 图表来源 - [MenuType.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/MenuType.java) - [ResourceNode.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/ResourceNode.java) 章节来源 - [MenuType.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/MenuType.java) - [ResourceNode.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/ResourceNode.java) - [ResourceServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/ResourceServiceImpl.java) ### Result 与 PageResult 统一响应封装 - Result - 结构:包含状态码、消息、数据体三部分,保证接口返回结构一致。 - 使用:成功路径返回 data,失败路径设置错误码与消息,由全局异常处理器统一转换。 - PageResult - 结构:包含当前页、每页大小、总记录数、总页数、数据列表等分页元信息。 - 使用:服务层返回分页数据后,通过 PageConverter 转换为 PageResult。 ```mermaid classDiagram class Result { + "状态码" + "消息" + "数据体" } class PageResult { + "当前页" + "每页大小" + "总记录数" + "总页数" + "数据列表" } class ResultCodeEnum { + "枚举定义" } PageResult --> Result : "引用" Result --> ResultCodeEnum : "使用" ``` 图表来源 - [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) 章节来源 - [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) ### DTO/Param 设计原则与字段验证规则 - 设计原则 - 单一职责:DTO 仅承载传输所需字段,Param 仅承载入参与校验。 - 最小暴露:对外只暴露必要字段,避免泄露内部实现细节。 - 可组合:通过继承 BaseDTO/BaseParam 复用公共能力。 - 字段验证规则 - 优先使用注解式校验(如非空、长度、格式),结合 AssertUtils 进行业务级断言。 - 对复杂校验逻辑在服务层集中处理,保持 Controller 简洁。 - 转换策略 - 使用 BeanCopyUtils 完成 DTO/Param/Entity 之间的属性映射。 - 对于复杂映射场景,可在服务层编写专用转换器,避免在 DTO/Param 中耦合业务逻辑。 ```mermaid flowchart TD Start(["开始"]) --> Validate["参数校验(注解/断言)"] Validate --> Valid{"校验通过?"} Valid --> |否| ReturnError["返回错误Result"] Valid --> |是| Convert["对象转换(BeanCopyUtils)"] Convert --> Business["执行业务逻辑"] Business --> BuildResult["构建Result/PageResult"] BuildResult --> End(["结束"]) ReturnError --> End ``` 图表来源 - [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) - [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) 章节来源 - [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) - [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) ### 领域模型扩展指导与自定义数据对象规范 - 扩展 BaseDTO/BaseParam - 新增 DTO:继承 BaseDTO,仅添加必要字段,保持不可变性。 - 新增 Param:继承 BaseParam,集中声明校验注解,必要时提供默认值。 - 自定义数据对象 - 命名规范:以业务语义命名,避免技术实现词汇。 - 字段类型:优先使用标准类型与枚举,减少歧义。 - 序列化:如需控制 JSON 输出,仅在 DTO 上标注,不在 Param 上标注。 - 与实体的关系 - BaseEntity/OwenedEntity 作为持久化基类,DTO/Param 不应直接继承实体基类。 - 通过 BeanCopyUtils 进行单向或双向转换,保持边界清晰。 - 枚举设计最佳实践 - 单一来源:避免重复定义相似枚举,如MenuTypeEnum和MenuType的统一。 - 工厂方法:提供fromCode等方法简化DB值到枚举的转换。 - 业务逻辑:在枚举中封装相关的业务规则,如层级约束验证。 ```mermaid classDiagram class BaseEntity { + "公共持久化字段" } class OwnedEntity { + "数据归属字段" } class CustomDTO class CustomParam class MenuType { + "节点类型定义" + "层级约束验证" } OwnedEntity --|> BaseEntity : "继承" CustomDTO --|> BaseDTO : "继承" CustomParam --|> BaseParam : "继承" MenuType <.. CustomDTO : "使用" ``` 图表来源 - [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) - [MenuType.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/MenuType.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) - [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) - [MenuType.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/MenuType.java) ## 依赖关系分析 - 组件内聚与耦合 - BaseDTO/BaseParam 低耦合,仅依赖基础类型与工具类。 - Result/PageResult 被各层广泛引用,需保持稳定。 - BeanCopyUtils/PageConverter 为横切工具,降低转换复杂度。 - MenuType 作为业务枚举,被ResourceNode和相关服务类引用。 - 外部依赖 - 全局异常处理器与 Result 配合,确保错误路径一致。 - 业务模块通过继承 BaseDTO/BaseParam 复用能力。 ```mermaid graph LR BaseDTO --> BeanCopyUtils BaseParam --> BeanCopyUtils PageResult --> PageConverter GlobalExceptionHandlerAdvice --> Result Result --> ResultCodeEnum MenuType --> ResourceNode ResourceNode --> ResourceServiceImpl ``` 图表来源 - [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) - [BeanCopyUtils.java](file://crm-base/src/main/java/com/crm/base/utils/BeanCopyUtils.java) - [PageConverter.java](file://crm-base/src/main/java/com/crm/base/utils/PageConverter.java) - [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.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) - [MenuType.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/MenuType.java) - [ResourceNode.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/ResourceNode.java) - [ResourceServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/ResourceServiceImpl.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) - [BeanCopyUtils.java](file://crm-base/src/main/java/com/crm/base/utils/BeanCopyUtils.java) - [PageConverter.java](file://crm-base/src/main/java/com/crm/base/utils/PageConverter.java) - [PageResult.java](file://crm-base/src/main/java/com/crm/base/domain/result/PageResult.java) - [GlobalExceptionHandlerAdvice.java](file://crm-base/src/main/java/com/crm/base/advice/GlobalExceptionHandlerAdvice.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) - [MenuType.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/MenuType.java) - [ResourceNode.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/ResourceNode.java) - [ResourceServiceImpl.java](file://crm-auth/src/main/java/com/crm/auth/service/impl/ResourceServiceImpl.java) ## 性能考虑 - 对象转换 - 使用 BeanCopyUtils 批量转换,避免逐字段赋值带来的样板代码与潜在性能损耗。 - 对高频转换场景,可缓存映射配置以减少反射开销。 - 分页查询 - 通过 PageConverter 将数据库分页结果转换为 PageResult,避免全量加载。 - 合理设置每页大小,避免过大导致内存压力。 - 响应封装 - Result/PageResult 尽量轻量,避免在响应中包含冗余字段。 - 对大对象返回时,考虑按需字段选择与延迟加载。 - 枚举使用 - MenuType等枚举类型在内存中共享,避免重复实例化。 - 使用fromCode方法进行枚举查找,避免字符串比较的性能开销。 [本节为通用性能建议,不直接分析具体文件] ## 故障排查指南 - 常见异常 - 业务异常:BusinessErrorException,表示业务规则不满足。 - 参数缺失:MissingParameterException,表示必填参数未传入。 - 权限异常:PermissionErrorException,表示权限不足。 - 资源不存在:ResourceNotExistException,表示目标资源不存在。 - 全局处理 - GlobalExceptionHandlerAdvice 捕获上述异常并转换为统一 Result,确保前端一致体验。 - 调试建议 - 在 Controller 层打印入参与关键中间结果。 - 使用 AssertUtils 快速定位参数问题。 - 检查 ResultCodeEnum 的状态码是否与前端约定一致。 - 枚举相关问题 - 检查MenuType.fromCode()是否能正确解析DB存储的值。 - 验证层级约束isLegalChild()的逻辑是否符合业务需求。 章节来源 - [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) - [ResultCodeEnum.java](file://crm-base/src/main/java/com/crm/base/domain/result/ResultCodeEnum.java) - [MenuType.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/MenuType.java) ## 结论 通过 BaseDTO/BaseParam 的基类抽象、Result/PageResult 的统一封装,以及 BeanCopyUtils/PageConverter 的工具支撑,项目在领域模型层面实现了高内聚、低耦合与一致的交互契约。移除了冗余的MenuTypeEnum枚举,统一使用MenuType作为节点类型定义的唯一来源,进一步提升了代码的一致性和可维护性。遵循本文的设计原则与扩展规范,可有效提升代码可维护性与团队协作效率。 [本节为总结性内容,不直接分析具体文件] ## 附录 - 最佳实践清单 - DTO/Param 严格分离,避免混用。 - 校验优先注解,复杂逻辑下沉至服务层。 - 转换统一使用工具类,禁止手写样板代码。 - 异常统一抛出并由全局处理器收敛。 - 枚举设计遵循单一来源原则,避免重复定义。 - 参考示例 - 登录参数:LoginParam 继承 BaseParam,集中声明校验注解。 - 用户信息:UserInfoDTO 继承 BaseDTO,仅暴露必要字段。 - 菜单类型:MenuType 定义节点类型及层级约束,ResourceNode 使用MenuType作为类型字段。 章节来源 - [LoginParam.java](file://crm-auth/src/main/java/com/crm/auth/domain/param/LoginParam.java) - [UserInfoDTO.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/UserInfoDTO.java) - [BaseParam.java](file://crm-base/src/main/java/com/crm/base/domain/param/BaseParam.java) - [BaseDTO.java](file://crm-base/src/main/java/com/crm/base/domain/dto/BaseDTO.java) - [MenuType.java](file://crm-auth/src/main/java/com/crm/auth/domain/enums/MenuType.java) - [ResourceNode.java](file://crm-auth/src/main/java/com/crm/auth/domain/dto/ResourceNode.java)