# label_backend Swagger 参数注解与 DTO 化设计 > 日期:2026-04-15 > 范围:`label_backend` 对外 REST API 的 Swagger/OpenAPI 文档增强 ## 1. 背景 当前 `label_backend` 已经在 Controller 层使用了 `@Tag` 和 `@Operation`,少量 DTO 也已有 `@Schema` 注解,因此 Swagger 页面可以展示基础接口列表和部分对象结构。 但现状仍存在几个明显问题: - 很多路径参数、查询参数、表单参数缺少名称、类型、取值和含义说明 - 多个接口仍使用 `Map` 或 `Map` 作为请求体,Swagger 无法准确展示字段名、字段类型和字段说明 - 一些固定结构响应仍以 `Map` 返回,Swagger 只能显示匿名对象 - 部分接口直接暴露实体类,而实体字段尚未补齐 Swagger 字段描述 - 通用返回包装 `Result`、`PageResult` 没有字段级别文档说明 用户目标很明确:在 Swagger 中看到所有接口参数的名称、类型和含义。 ## 2. 目标 本次改造完成后,`label_backend` 的 Swagger 页面应满足以下目标: - 所有公开接口都能展示清晰的路径参数、查询参数、请求头参数、表单参数说明 - 所有固定结构的请求体都使用 DTO 建模,并为每个字段提供名称、类型、必填性和含义说明 - 所有固定结构的主要响应对象都能展示字段说明 - 所有分页与统一返回包装的字段含义清晰可见 - 不改变现有接口路径、HTTP 方法和字段名称,尽量保持对现有调用方兼容 ## 3. 非目标 本次不做以下事情: - 不重构整体业务流程 - 不调整接口 URL、HTTP 方法和权限策略 - 不强制把所有实体类都替换成专门的 Response DTO - 不把完全动态的业务 JSON 全量重建成复杂深层对象,只对固定边界做显式包装 - 不顺手做无关的代码整理或目录重构 ## 4. 设计原则 ### 4.1 DTO-first 凡是 Swagger 需要清楚展示字段名、字段类型和字段说明的固定结构请求体,都应优先使用 DTO,而不是 `Map`。 ### 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` - `PageResult` ### 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` 但字段稳定,应收敛为 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` 应说明: - `code`:业务状态码 - `data`:接口返回主体 - `message`:失败或补充说明 `PageResult` 应说明: - `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`、`PageResult` 补齐字段说明 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 可读性和接口契约清晰度