Files
label_backend/docs/superpowers/specs/2026-04-15-label-backend-swagger-annotations-design.md

302 lines
9.0 KiB
Markdown
Raw Normal View History

# label_backend Swagger 参数注解与 DTO 化设计
> 日期2026-04-15
> 范围:`label_backend` 对外 REST API 的 Swagger/OpenAPI 文档增强
## 1. 背景
当前 `label_backend` 已经在 Controller 层使用了 `@Tag``@Operation`,少量 DTO 也已有 `@Schema` 注解,因此 Swagger 页面可以展示基础接口列表和部分对象结构。
但现状仍存在几个明显问题:
- 很多路径参数、查询参数、表单参数缺少名称、类型、取值和含义说明
- 多个接口仍使用 `Map<String, Object>``Map<String, String>` 作为请求体Swagger 无法准确展示字段名、字段类型和字段说明
- 一些固定结构响应仍以 `Map<String, Object>` 返回Swagger 只能显示匿名对象
- 部分接口直接暴露实体类,而实体字段尚未补齐 Swagger 字段描述
- 通用返回包装 `Result<T>``PageResult<T>` 没有字段级别文档说明
用户目标很明确:在 Swagger 中看到所有接口参数的名称、类型和含义。
## 2. 目标
本次改造完成后,`label_backend` 的 Swagger 页面应满足以下目标:
- 所有公开接口都能展示清晰的路径参数、查询参数、请求头参数、表单参数说明
- 所有固定结构的请求体都使用 DTO 建模,并为每个字段提供名称、类型、必填性和含义说明
- 所有固定结构的主要响应对象都能展示字段说明
- 所有分页与统一返回包装的字段含义清晰可见
- 不改变现有接口路径、HTTP 方法和字段名称,尽量保持对现有调用方兼容
## 3. 非目标
本次不做以下事情:
- 不重构整体业务流程
- 不调整接口 URL、HTTP 方法和权限策略
- 不强制把所有实体类都替换成专门的 Response DTO
- 不把完全动态的业务 JSON 全量重建成复杂深层对象,只对固定边界做显式包装
- 不顺手做无关的代码整理或目录重构
## 4. 设计原则
### 4.1 DTO-first
凡是 Swagger 需要清楚展示字段名、字段类型和字段说明的固定结构请求体,都应优先使用 DTO而不是 `Map<String, Object>`
### 4.2 文档增强优先,行为保持不变
本次的核心是 API 契约可读性增强,因此:
- Controller 仍调用原有 Service
- 参数字段名保持不变
- 业务语义、状态流转、权限校验保持不变
### 4.3 固定结构显式化,动态结构边界化
如果接口返回的是稳定字段集合,应使用明确 DTO 或明确对象字段注解。
如果业务内部结果本身仍是动态 JSON则至少提供一个固定外层 DTO把最外层字段含义说明清楚避免 Swagger 展示匿名 `Map`
### 4.4 最小可控改动
优先修改 Controller 入口、DTO 定义和 Swagger 展示对象,尽量不侵入 Service 深层逻辑。
## 5. 目标改造范围
### 5.1 Controller
本次覆盖以下 10 个 Controller
- `AuthController`
- `CompanyController`
- `ExportController`
- `ExtractionController`
- `QaController`
- `SourceController`
- `SysConfigController`
- `TaskController`
- `UserController`
- `VideoController`
### 5.2 通用返回模型
- `Result<T>`
- `PageResult<T>`
### 5.3 现有 DTO
- `LoginRequest`
- `LoginResponse`
- `SourceResponse`
- `TaskResponse`
- `UserInfoResponse`
### 5.4 当前直接暴露给 Swagger 的实体
- `SysUser`
- `SysCompany`
- `SysConfig`
- `TrainingDataset`
- `ExportBatch`
- `VideoProcessJob`
## 6. DTO 改造策略
### 6.1 必须从 Map 重构为 DTO 的请求体
以下接口应从匿名请求体改为明确 DTO
- `TaskController#createTask`
- 新增 `CreateTaskRequest`
- `TaskController#reassign`
- 新增 `TaskReassignRequest`
- `VideoController#createJob`
- 新增 `VideoProcessCreateRequest`
- `VideoController#handleCallback`
- 新增 `VideoProcessCallbackRequest`
- `CompanyController#update`
- 新增明确请求 DTO
- `CompanyController#updateStatus`
- 新增明确请求 DTO
- `ExportController#createBatch`
- 新增明确请求 DTO
- `UserController` 中如仍存在匿名请求体,也统一改成 DTO
### 6.2 固定结构响应优先改为 DTO
以下返回如果当前为 `Map<String, Object>` 但字段稳定,应收敛为 DTO
- 导出与微调相关状态响应
- 视频回调相关固定结构响应
- 系统配置项列表响应
### 6.3 动态结果场景
`ExtractionController``QaController` 可能仍涉及结构化 JSON 结果。处理原则如下:
- 如果最外层字段稳定,则增加外层 DTO 说明
- 如果内部 `items` 仍允许动态内容,则在 DTO 字段级别说明该字段承载的业务 JSON 结构
## 7. Swagger 注解标准
### 7.1 Controller 方法
每个接口方法统一遵循:
- `@Tag`
- `@Operation(summary = "...", description = "...")`
- 对路径参数、查询参数、请求头参数、表单参数补 `@Parameter`
- 对请求体补 `@io.swagger.v3.oas.annotations.parameters.RequestBody`
参数描述至少包含:
- 参数业务含义
- 是否必填
- 枚举值范围或典型值
- 分页默认值或限制条件
### 7.2 DTO 字段
所有公开请求/响应 DTO 字段统一使用:
- `@Schema(description = "...", example = "...")`
必要时增加:
- `@NotNull`
- `@NotBlank`
- `@Valid`
### 7.3 通用包装类
`Result<T>` 应说明:
- `code`:业务状态码
- `data`:接口返回主体
- `message`:失败或补充说明
`PageResult<T>` 应说明:
- `items`:当前页数据列表
- `total`:总记录数
- `page`:当前页码,从 1 开始
- `pageSize`:每页条数
### 7.4 直接暴露实体
对于当前直接暴露给 Swagger 的实体类,给字段补齐 `@Schema` 说明,但不在本次强制转换为 Response DTO。
## 8. 代码组织方案
建议在 `dto/` 下继续保持扁平化风格,新增与接口语义一致的请求和响应类,命名以业务动作为中心,例如:
- `CreateTaskRequest`
- `TaskReassignRequest`
- `VideoProcessCreateRequest`
- `VideoProcessCallbackRequest`
- `CompanyUpdateRequest`
- `CompanyStatusUpdateRequest`
- `ExportBatchCreateRequest`
如果某个响应只在单个 Controller 使用,但字段固定,也放在 `dto/` 下,而不是内联 `Map`
## 9. 兼容性要求
为了避免影响现有调用方,本次必须满足:
- 接口 URL 不变
- HTTP 方法不变
- JSON 字段名称不变
- Multipart 参数名不变
- 路径参数名和查询参数名不变
DTO 只是显式建模现有契约,不是重新设计契约。
## 9.1 README 约束同步
本次设计不仅要求代码层落地,还要求将 Swagger/DTO 约束写入项目 `README.md` 的开发规范中,作为后续接口开发的长期规则。
README 中至少应明确以下要求:
- 所有对外接口参数必须在 Swagger 中清楚展示名称、类型和含义
- 固定结构请求体禁止继续使用匿名 `Map`,必须定义 DTO
- 固定结构响应应优先显式建模,避免 Swagger 展示匿名对象
- 通用返回体和分页包装也必须维护字段说明
## 10. 测试策略
由于本次会把匿名请求体改为 DTO需要用测试确认请求绑定行为没有被改坏。
测试策略如下:
- 优先补或更新 Controller 测试
- 覆盖 DTO 替换后的 JSON 反序列化
- 验证关键接口的请求字段名保持不变
- 验证原有成功路径和主要失败路径仍成立
至少应覆盖:
- 创建任务
- 重指派任务
- 创建视频处理任务
- 接收视频回调
- 创建导出批次
- 公司更新和状态更新
## 11. 风险与处理
### 11.1 风险:字段名不一致导致请求绑定失败
处理方式:
- DTO 字段严格对齐当前请求 JSON 的既有字段名
- 使用 Controller 测试验证兼容性
### 11.2 风险:动态 JSON 过度 DTO 化,导致业务边界变复杂
处理方式:
- 只对固定边界建模
- 动态业务内容保留为受控字段,不做过度深挖
### 11.3 风险:实体类字段太多,注解工作量大
处理方式:
- 只处理当前实际暴露到 Swagger 的实体
- 优先处理高频接口涉及对象
## 12. 实施顺序
推荐按以下顺序实施:
1.`Result<T>``PageResult<T>` 补齐字段说明
2. 给已有公开 DTO 补齐 `@Schema`
3. 将匿名请求体改造成 DTO并更新对应 Controller
4. 将固定结构的 `Map` 响应改造成 DTO
5. 为直接暴露的实体补齐 `@Schema`
6. 统一补齐 Controller 参数 `@Parameter` 注解
7. 更新或新增相关测试并执行验证
## 13. 验收标准
验收通过应满足以下条件:
- Swagger 页面中所有公开接口参数都能看到名称、类型和含义
- 所有固定结构请求体不再以匿名 `Map` 展示
- 主要响应对象字段说明齐全
- 通用返回体字段说明齐全
- `README.md` 已写入 Swagger/DTO 文档约束
- Controller 相关测试通过
- 未引入接口路径或字段名兼容性破坏
## 14. 决策总结
本次采用“DTO-first API 文档化”方案:
- 请求体优先 DTO 化
- 固定结构响应优先显式建模
- Controller 参数注释统一化
- 通用返回体和当前暴露实体补齐 Swagger 字段说明
- 在不改变业务语义的前提下,最大化提升 Swagger 可读性和接口契约清晰度