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

领域模型

**本文引用的文件** - [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) - [SysMenu.java](file://crm-auth/src/main/java/com/crm/auth/domain/entity/SysMenu.java)

更新摘要

所做更改

  • 更新了菜单类型枚举的统一化说明,移除已废弃的MenuTypeEnum引用
  • 新增MenuType枚举的详细使用说明和最佳实践
  • 更新了ResourceNode DTO与MenuType的集成示例
  • 完善了领域模型中枚举类型的标准化指导

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能考虑
  8. 故障排查指南
  9. 结论
  10. 附录

简介

本文件面向领域模型与数据契约,系统性说明 BaseDTO、BaseParam 的基类设计与继承关系,统一响应 Result 与分页结果 PageResult 的结构与用法,阐述 DTO 与 Param 的设计原则、字段验证规则与转换策略,并给出领域模型的扩展指导与自定义数据对象的创建规范。目标是帮助开发者在 CRM 后端项目中以一致、可维护的方式定义数据传输对象、参数对象以及统一的接口响应格式。

更新 本项目已统一菜单类型枚举,移除了废弃的MenuTypeEnum,仅保留MenuType(CATALOG/MENU/BUTTON)作为权威定义,确保领域模型词汇的一致性。

项目结构

本项目采用多模块组织,领域模型相关的基础类型集中在 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(包含统一的MenuType)
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["domain/entity/SysMenu"]
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
  • BaseParam.java
  • Result.java
  • PageResult.java
  • BeanCopyUtils.java
  • PageConverter.java
  • GlobalExceptionHandlerAdvice.java
  • BaseEntity.java
  • OwnedEntity.java
  • LoginParam.java
  • UserInfoDTO.java
  • MenuType.java
  • ResourceNode.java
  • SysMenu.java

章节来源

  • BaseDTO.java
  • BaseParam.java
  • Result.java
  • PageResult.java
  • BeanCopyUtils.java
  • PageConverter.java
  • GlobalExceptionHandlerAdvice.java
  • BaseEntity.java
  • OwnedEntity.java
  • LoginParam.java
  • UserInfoDTO.java
  • MenuType.java
  • ResourceNode.java
  • SysMenu.java

核心组件

  • BaseDTO:所有数据传输对象的基类,提供统一的序列化、审计或扩展字段约定,便于跨层传递数据。
  • BaseParam:所有请求参数的基类,集中承载校验注解、分页与排序等通用能力,简化 Controller 入参定义。
  • Result:统一响应封装,包含状态码、消息与数据体,确保前后端交互一致性。
  • PageResult:分页结果封装,聚合页码、总数、列表数据等分页元信息。
  • BeanCopyUtils:对象拷贝工具,用于 DTO/Param/Entity 之间的属性映射与转换。
  • PageConverter:分页转换工具,将框架分页对象转换为 PageResult。
  • AssertUtils:断言工具,用于快速进行参数合法性校验。
  • GlobalExceptionHandlerAdvice:全局异常处理器,将业务异常转换为统一 Result。
  • MenuType:统一的菜单类型枚举,定义了CATALOG(目录)、MENU(菜单)、BUTTON(按钮)三种类型,替代了之前废弃的MenuTypeEnum。

章节来源

  • BaseDTO.java
  • BaseParam.java
  • Result.java
  • PageResult.java
  • BeanCopyUtils.java
  • PageConverter.java
  • AssertUtils.java
  • GlobalExceptionHandlerAdvice.java
  • MenuType.java

架构总览

下图展示了领域模型在请求链路中的角色与交互:Controller 接收 BaseParam 派生参数,经服务层处理返回 Result 或 PageResult;DTO 作为跨层数据载体,通过 BeanCopyUtils 与 Entity 相互转换。MenuType 作为统一的领域概念,贯穿整个权限资源树的管理流程。

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->>Service : "MenuType 验证(isLegalChild)"
Service-->>Controller : "业务结果(DTO/Entity)"
Controller->>Response : "封装为Result/PageResult"
Response-->>Client : "JSON 响应"

图表来源

  • GlobalExceptionHandlerAdvice.java
  • BeanCopyUtils.java
  • Result.java
  • PageResult.java
  • MenuType.java

详细组件分析

BaseDTO 与 BaseParam 基类设计

  • BaseDTO
    • 职责:作为数据传输对象的基类,统一序列化行为与扩展点,避免在各 DTO 中重复定义公共字段。
    • 设计要点:仅暴露必要字段,保持不可变或最小可变性;避免携带持久化细节。
  • BaseParam
    • 职责:作为请求参数的基类,集中声明校验注解、分页与排序等通用能力。
    • 设计要点:与 Controller 入参解耦,便于单元测试与 Mock;支持可选字段与默认值。
classDiagram
class BaseDTO {
+ "公共字段与行为"
}
class BaseParam {
+ "公共字段与行为"
}
class UserInfoDTO
class LoginParam
UserInfoDTO --|> BaseDTO : "继承"
LoginParam --|> BaseParam : "继承"

图表来源

  • BaseDTO.java
  • BaseParam.java
  • UserInfoDTO.java
  • LoginParam.java

章节来源

  • BaseDTO.java
  • BaseParam.java
  • UserInfoDTO.java
  • LoginParam.java

MenuType 统一枚举设计

更新 项目已统一菜单类型枚举,移除了废弃的MenuTypeEnum,仅保留MenuType作为权威定义。

  • MenuType
    • 职责:定义权限资源树的节点类型,包括CATALOG(目录容器)、MENU(可导航页面)、BUTTON(按钮权限点)。
    • 设计要点:提供fromCode工厂方法进行数据库tinyint值反查,isLegalChild方法验证父子节点关系的合法性。
    • 数据库映射:CATALOG(1)、MENU(2)、BUTTON(3),对应sys_menu表的menuType字段。
classDiagram
class MenuType {
+ "CATALOG : 目录容器"
+ "MENU : 可导航页面"
+ "BUTTON : 按钮权限点"
+ "fromCode(Integer) : MenuType"
+ "isLegalChild(MenuType, MenuType) : boolean"
}
class ResourceNode {
+ "type : MenuType"
+ "fromEntity(SysMenu) : ResourceNode"
+ "toEntity() : SysMenu"
}
class SysMenu {
+ "menuType : Integer"
+ "description : String"
+ "perms : String"
+ "denyBehavior : String"
+ "status : String"
+ "apiUrl : String"
}
ResourceNode --> MenuType : "使用"
SysMenu --> MenuType : "映射"

图表来源

  • MenuType.java
  • ResourceNode.java
  • SysMenu.java

章节来源

  • MenuType.java
  • ResourceNode.java
  • SysMenu.java

Result 与 PageResult 统一响应封装

  • Result
    • 结构:包含状态码、消息、数据体三部分,保证接口返回结构一致。
    • 使用:成功路径返回 data,失败路径设置错误码与消息,由全局异常处理器统一转换。
  • PageResult
    • 结构:包含当前页、每页大小、总记录数、总页数、数据列表等分页元信息。
    • 使用:服务层返回分页数据后,通过 PageConverter 转换为 PageResult。
classDiagram
class Result {
+ "状态码"
+ "消息"
+ "数据体"
}
class PageResult {
+ "当前页"
+ "每页大小"
+ "总记录数"
+ "总页数"
+ "数据列表"
}
class ResultCodeEnum {
+ "枚举定义"
}
PageResult --> Result : "引用"
Result --> ResultCodeEnum : "使用"

图表来源

  • Result.java
  • PageResult.java
  • ResultCodeEnum.java

章节来源

  • Result.java
  • PageResult.java
  • ResultCodeEnum.java

DTO/Param 设计原则与字段验证规则

  • 设计原则
    • 单一职责:DTO 仅承载传输所需字段,Param 仅承载入参与校验。
    • 最小暴露:对外只暴露必要字段,避免泄露内部实现细节。
    • 可组合:通过继承 BaseDTO/BaseParam 复用公共能力。
  • 字段验证规则
    • 优先使用注解式校验(如非空、长度、格式),结合 AssertUtils 进行业务级断言。
    • 对复杂校验逻辑在服务层集中处理,保持 Controller 简洁。
    • MenuType 相关的验证使用MenuType.isLegalChild方法进行层级约束检查。
  • 转换策略
    • 使用 BeanCopyUtils 完成 DTO/Param/Entity 之间的属性映射。
    • 对于复杂映射场景,可在服务层编写专用转换器,避免在 DTO/Param 中耦合业务逻辑。
    • MenuType与Integer之间的转换使用MenuType.fromCode和getCode方法。
flowchart TD
Start(["开始"]) --> Validate["参数校验(注解/断言)"]
Validate --> Valid{"校验通过?"}
Valid --> |否| ReturnError["返回错误Result"]
Valid --> |是| Convert["对象转换(BeanCopyUtils)"]
Convert --> MenuTypeCheck["MenuType 层级验证"]
MenuTypeCheck --> Business["执行业务逻辑"]
Business --> BuildResult["构建Result/PageResult"]
BuildResult --> End(["结束"])
ReturnError --> End

图表来源

  • AssertUtils.java
  • BeanCopyUtils.java
  • Result.java
  • PageResult.java
  • MenuType.java

章节来源

  • AssertUtils.java
  • BeanCopyUtils.java
  • Result.java
  • PageResult.java
  • MenuType.java

领域模型扩展指导与自定义数据对象规范

  • 扩展 BaseDTO/BaseParam
    • 新增 DTO:继承 BaseDTO,仅添加必要字段,保持不可变性。
    • 新增 Param:继承 BaseParam,集中声明校验注解,必要时提供默认值。
  • 自定义数据对象
    • 命名规范:以业务语义命名,避免技术实现词汇。
    • 字段类型:优先使用标准类型与枚举,减少歧义。
    • 序列化:如需控制 JSON 输出,仅在 DTO 上标注,不在 Param 上标注。
    • 枚举使用:使用统一的领域枚举(如MenuType),避免重复定义。
  • 与实体的关系
    • BaseEntity/OwenedEntity 作为持久化基类,DTO/Param 不应直接继承实体基类。
    • 通过 BeanCopyUtils 进行单向或双向转换,保持边界清晰。
    • 枚举字段通过fromCode和getCode方法进行数据库值与枚举值的转换。
classDiagram
class BaseEntity {
+ "公共持久化字段"
}
class OwnedEntity {
+ "数据归属字段"
}
class CustomDTO
class CustomParam
class MenuType {
+ "CATALOG/MENU/BUTTON"
+ "fromCode/getCode"
}
OwnedEntity --|> BaseEntity : "继承"
CustomDTO --|> BaseDTO : "继承"
CustomParam --|> BaseParam : "继承"
CustomDTO --> MenuType : "使用"

图表来源

  • BaseEntity.java
  • OwnedEntity.java
  • BaseDTO.java
  • BaseParam.java
  • MenuType.java

章节来源

  • BaseEntity.java
  • OwnedEntity.java
  • BaseDTO.java
  • BaseParam.java
  • MenuType.java

依赖关系分析

  • 组件内聚与耦合
    • BaseDTO/BaseParam 低耦合,仅依赖基础类型与工具类。
    • Result/PageResult 被各层广泛引用,需保持稳定。
    • BeanCopyUtils/PageConverter 为横切工具,降低转换复杂度。
    • MenuType 作为统一枚举,被ResourceNode、SysMenu等相关组件引用。
  • 外部依赖
    • 全局异常处理器与 Result 配合,确保错误路径一致。
    • 业务模块通过继承 BaseDTO/BaseParam 复用能力。
    • MenuType 消除了MenuTypeEnum的冗余,简化了依赖关系。
graph LR
BaseDTO --> BeanCopyUtils
BaseParam --> BeanCopyUtils
PageResult --> PageConverter
GlobalExceptionHandlerAdvice --> Result
Result --> ResultCodeEnum
ResourceNode --> MenuType
SysMenu --> MenuType
MenuType --> BeanCopyUtils

图表来源

  • BaseDTO.java
  • BaseParam.java
  • BeanCopyUtils.java
  • PageConverter.java
  • PageResult.java
  • GlobalExceptionHandlerAdvice.java
  • Result.java
  • ResultCodeEnum.java
  • MenuType.java
  • ResourceNode.java
  • SysMenu.java

章节来源

  • BaseDTO.java
  • BaseParam.java
  • BeanCopyUtils.java
  • PageConverter.java
  • PageResult.java
  • GlobalExceptionHandlerAdvice.java
  • Result.java
  • ResultCodeEnum.java
  • MenuType.java
  • ResourceNode.java
  • SysMenu.java

性能考虑

  • 对象转换
    • 使用 BeanCopyUtils 批量转换,避免逐字段赋值带来的样板代码与潜在性能损耗。
    • 对高频转换场景,可缓存映射配置以减少反射开销。
  • 分页查询
    • 通过 PageConverter 将数据库分页结果转换为 PageResult,避免全量加载。
    • 合理设置每页大小,避免过大导致内存压力。
  • 响应封装
    • Result/PageResult 尽量轻量,避免在响应中包含冗余字段。
    • 对大对象返回时,考虑按需字段选择与延迟加载。
  • 枚举使用
    • MenuType 提供静态方法避免重复计算,提升性能。
    • fromCode方法使用流式API进行高效查找。

故障排查指南

  • 常见异常
    • 业务异常:BusinessErrorException,表示业务规则不满足。
    • 参数缺失:MissingParameterException,表示必填参数未传入。
    • 权限异常:PermissionErrorException,表示权限不足。
    • 资源不存在:ResourceNotExistException,表示目标资源不存在。
  • 全局处理
    • GlobalExceptionHandlerAdvice 捕获上述异常并转换为统一 Result,确保前端一致体验。
  • 调试建议
    • 在 Controller 层打印入参与关键中间结果。
    • 使用 AssertUtils 快速定位参数问题。
    • 检查 ResultCodeEnum 的状态码是否与前端约定一致。
    • 验证 MenuType 的层级关系是否符合预期。

章节来源

  • GlobalExceptionHandlerAdvice.java
  • BusinessErrorException.java
  • MissingParameterException.java
  • PermissionErrorException.java
  • ResourceNotExistException.java
  • Result.java
  • ResultCodeEnum.java
  • MenuType.java

结论

通过 BaseDTO/BaseParam 的基类抽象、Result/PageResult 的统一封装,以及 BeanCopyUtils/PageConverter 的工具支撑,项目在领域模型层面实现了高内聚、低耦合与一致的交互契约。更新 通过统一MenuType枚举,消除了MenuTypeEnum的冗余,进一步简化了领域模型的词汇体系。遵循本文的设计原则与扩展规范,可有效提升代码可维护性与团队协作效率。

附录

  • 最佳实践清单
    • DTO/Param 严格分离,避免混用。
    • 校验优先注解,复杂逻辑下沉至服务层。
    • 转换统一使用工具类,禁止手写样板代码。
    • 异常统一抛出并由全局处理器收敛。
    • 使用统一的领域枚举(如MenuType),避免重复定义。
  • 参考示例
    • 登录参数:LoginParam 继承 BaseParam,集中声明校验注解。
    • 用户信息:UserInfoDTO 继承 BaseDTO,仅暴露必要字段。
    • 资源节点:ResourceNode 使用 MenuType 枚举,提供完整的CRUD操作。
  • 枚举使用规范
    • 使用MenuType.fromCode进行数据库值到枚举的转换。
    • 使用MenuType.getCode进行枚举到数据库值的转换。
    • 使用MenuType.isLegalChild验证父子节点的合法性。

章节来源

  • LoginParam.java
  • UserInfoDTO.java
  • BaseParam.java
  • BaseDTO.java
  • MenuType.java
  • ResourceNode.java