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.
4.5 KiB
4.5 KiB
Controller 出入参两类对象规范(Param / DTO)
Status: ready-for-agent ADR: ADR-0017
入参查询用
XxxParam,入参写入和出参都用XxxDTO,Entity 永不出现在 Controller 方法签名上。
一句话规则
- 写新接口:查询/分页 → 建
XxxParam extends BaseParam;写入/保存 → 参数 ≥3 建一个XxxDTO,≤2 保持@RequestParam - 写新出参:建
XxxDTO,业务类继承BaseDTO白拿id/createTime/updateTime - 想直接返回实体:不行
对象职责
| 类型 | 包 | 用途 | 继承 | 硬约束 |
|---|---|---|---|---|
XxxParam |
param/ |
查询/搜索/分页入参 | extends BaseParam |
必须经 PageConverter.toMpPage 转换 |
XxxDTO |
dto/ |
写入参 + 出参(双向) | 业务类 extends BaseDTO;统计/登录等无主键语义的不继承 |
fromEntity() / toEntity() 写在 DTO 上,Service 层调用 |
| Entity | domain/entity/ |
表结构映射 | extends BaseEntity |
禁止出现在任何 Controller 方法签名中 |
硬约束
- Entity 不出现在 Controller 方法签名上(入参出参都禁)
deleted不出现在任何 HTTP 响应中creatorId/updaterId不出现在任何 HTTP 响应中
Mass assignment 防御
全局 @ControllerAdvice + @InitBinder,dataBinder.setDisallowedFields(...) strip 掉服务端裁定字段:
createTime、updateTime、creatorId、updaterId、deleted、builtin
新增服务端裁定字段时必须同步更新此列表。
封装阈值
≥3 个参数封装为 XxxDTO;≤2 个保持 @RequestParam。纯参数个数,不看点参数形状。
命名规则
dto/ 包内所有 HTTP 出入参类一律 XxxDTO 后缀。内部传输对象(ButtonSeed、PermissionModuleDescriptor、UploadSession)不强制后缀。
绑定方式
隐式表单绑定(不加 @RequestBody),契合项目 application/x-www-form-urlencoded 契约。
存量改名清单
| 原名 | 新名 | 模块 |
|---|---|---|
RoleDetailVO |
RoleDTO |
crm-auth |
UserStatsVO |
UserStatsDTO |
crm-auth |
DictGroupVO |
DictGroupDTO |
crm-dict |
DictItemVO |
DictItemDTO |
crm-dict |
ResourceNode |
ResourceNodeDTO |
crm-auth |
存量违规回填清单(9 处)
| # | 违规 | 位置 | 改法 |
|---|---|---|---|
| 1 | 实体直收 | DictGroupController.saveOrUpdate(DictGroup) |
改为 saveOrUpdate(DictGroupDTO) |
| 2 | 实体直收 | DictItemController.saveOrUpdate(DictItem) |
改为 saveOrUpdate(DictItemDTO) |
| 3 | 实体直出 | RoleController.page → Result<PageResult<SysRole>> |
改为 Result<PageResult<RoleDTO>> |
| 4 | 实体直出 | SystemController.menuTree → List<SysMenu> |
改为 List<ResourceNodeDTO> |
| 5 | 实体直出 | SystemController.deptTree → List<SysDept> |
改为 List<DeptDTO> |
| 6 | 实体直出 | DictGroupController.enabledList → List<DictGroup> |
改为 List<DictGroupDTO> |
| 7 | 实体直出 | DictItemController.enabledList → List<DictItem> |
改为 List<DictItemDTO> |
| 8 | 分页绕过 | RoleController.page 自行 new Page<> |
改为 RoleParam extends BaseParam,经 PageConverter |
| 9 | @RequestBody |
SystemController.userPage |
去掉 @RequestBody,改表单绑定 |
前置条件
BaseDTO 必须先重构(当前仍是未改造版本):
- 改为
abstract类 - 只保留
id、createTime、updateTime - 三字段加
@JsonInclude(NON_NULL) - 移除
creatorId、updaterId、deleted及默认值 - 移除泛型
toEntity(Supplier)方法
术语表
| 术语 | 定义 |
|---|---|
Param (XxxParam) |
查询/搜索/分页入参对象,放 param/ 包,继承 BaseParam,经 PageConverter 转换 |
DTO (XxxDTO) |
双向传输对象,既是写入参又是出参,放 dto/ 包;业务类继承 BaseDTO |
| BaseParam | 分页参数基类,提供 current / size / asc / desc + PageConverter 转换 |
| BaseDTO | 出参基类(abstract),提供 id / createTime / updateTime + @JsonInclude(NON_NULL) |
| InitBinder 防护 | 全局 @InitBinder + setDisallowedFields,strip 服务端裁定字段防 mass assignment |
| PageConverter | 分页转换器,页大小上限收敛 + 排序字段白名单校验 |
| 封装阈值 | ≥3 个参数封 XxxDTO,≤2 保持 @RequestParam |
| Route A | 同一个 DTO 类同时做写入参和出参(用户已接受双契约字段代价) |