diff --git a/changelogs/2026-04/2026-04-25_swagger-error-code-display.md b/changelogs/2026-04/2026-04-25_swagger-error-code-display.md new file mode 100644 index 0000000..acbdbbf --- /dev/null +++ b/changelogs/2026-04/2026-04-25_swagger-error-code-display.md @@ -0,0 +1,55 @@ +# Swagger 响应状态自动列出 6 位业务码(#1412) + +**日期**: 2026-04-25 +**关联 PR**: #1413(初版)/ #1414 / #1415 / #1416(hotfix 链) +**工单**: [#1412](https://git.1814.love:8443/wx/HL/issues/1412) + +--- + +## 改造前 +Knife4j 接口文档每个接口的「响应状态」区只有: +- 200 OK +- 401 Unauthorized +- 403 Forbidden +- 404 Not Found + +#1391 引入的 6 位业务码(如 `400301 产品下架` / `500311 订单状态不允许取消`)前端在文档里看不到。 + +## 改造后 +每个接口的「响应状态」区显示 **193 个状态码**: +- HTTP 标准 4 个(200/401/403/404 保留) +- **6 位业务码 189 个**(从 ErrorCodeRegistry 自动收集,含 message) + +### 实例(GET /admin/agreement/page) +``` +状态码 说明 +200 OK +401 Unauthorized +403 Forbidden +404 Not Found +100000 系统异常,请稍后重试 +100001 参数非法: {0} +100002 数据不存在 +100003 操作不允许: {0} +100501 {0} ← 流控 +100502 {0} ← 幂等拦截 +100901 远程服务返回数据为空 ← Feign 透传 +... (189 个 6 位业务码) +``` + +## 实现路径(踩坑总结) +1. **PR #1413**:`Docket.globalResponseMessage` 注入 — Docket bean 创建时 `ErrorCodeRegistry.scan()` 还没跑(在 ApplicationRunner 阶段),codeMap 空,失败 +2. **PR #1414**:改用 `OperationBuilderPlugin` — 仍空,因为 plugin 也在 ApplicationRunner 之前被 swagger 触发 +3. **PR #1415**:删除 5 个 Knife4jConfig 的 `globalResponseMessage` 残留(避免覆盖 plugin) +4. **PR #1416**:**根本解** — `ErrorCodeRegistry` 改用 `@PostConstruct` 在 Bean 实例化时立即扫描,所有下游 Bean 拿到非空 codeMap + +## 影响 +- 5 个 MVC 业务服务(user/resource/product-v2/order-v2/mp)swagger 全生效 +- 接口数据结构无变化,只是**文档**新增响应状态展示 +- 业务接口/前端调用无需改动 + +## 经验沉淀 +**Spring Boot Bean 启动顺序**:`ApplicationRunner.run()` 在 `ApplicationContext.refresh()` 完全完成之后运行,但 swagger 等组件可能在 refresh 过程中已构建 OpenAPI 模型,此时 ApplicationRunner 还没跑。需要在 Bean 创建期就完成扫描的逻辑应该用 `@PostConstruct`。 + +## 验证 +浏览器访问任一接口的"响应状态"区,应看到 193 行响应码。