API 响应与错误处理规范
范围:框架层所有对外暴露的 HTTP API。 原则:HTTP 状态码表达传输层语义;响应体
code字段表达业务层语义。
设计理念
"HTTP 状态码归属网络/协议层;响应体 code 字段归属业务层。"
| 关注点 | 承载者 | 消费者 |
|---|---|---|
| 网络可达性、认证、限流 | HTTP 状态码 | 网关、Nginx、Service Mesh、浏览器 |
| 业务成功/失败详情 | Body code 字段 | 前端业务组件、下游服务 |
优势:
- 基础设施(Nginx、API 网关、Sentinel)可直接根据 HTTP 状态码处理,无需反序列化 JSON。
- 前端网络拦截器(如 Axios)统一处理 HTTP 状态码;业务组件只读取
data。 - 每个响应均携带
traceId,实现跨网关与微服务日志的端到端可观测性。
标准响应结构
所有响应必须使用 Content-Type: application/json; charset=utf-8。
成功响应
HTTP 200 OK:
json
{
"code": 0,
"msg": "success",
"data": {
"userId": 1024,
"username": "zhangsan"
},
"traceId": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
}| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
code | int | Y | 0 表示成功,非 0 表示业务错误 |
msg | String | Y | 面向用户的提示信息;前端可展示或忽略 |
data | Object / Array / null | Y | 业务数据;为空时返回 null 或 {} |
traceId | String | Y | 分布式追踪 ID |
分页成功响应
分页元数据嵌套在 data 内部,保持顶层结构统一:
json
{
"code": 0,
"msg": "success",
"data": {
"items": [],
"total": 1024,
"page": 1,
"pageSize": 20,
"hasNext": true
},
"traceId": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d"
}错误响应
HTTP 4xx / 5xx:
json
{
"code": 25400,
"msg": "密码长度不能少于 8 位",
"traceId": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
"data": [
{
"field": "password",
"issue": "MinLength",
"message": "密码长度不能少于 8 位"
}
]
}| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
code | int | Y | 5 位业务错误码 |
msg | String | Y | 面向用户的错误文案;前端可直接 Toast |
traceId | String | Y | 所有错误响应必须携带 |
HTTP 状态码参考
只使用以下状态码,禁止自定义语义。
2xx — 成功
| 码 | 含义 | 使用场景 |
|---|---|---|
200 OK | 成功 | GET、POST、PUT 标准操作 |
4xx — 客户端错误(前端处理;后端不告警)
| 码 | 含义 | 使用场景 |
|---|---|---|
400 Bad Request | 语法/逻辑错误 | JSON 格式错误、必填请求头缺失、非法状态流转 |
401 Unauthorized | 认证失败 | Token 缺失/伪造/过期;用户名密码错误 |
403 Forbidden | 鉴权失败 | 身份已知但无权限;越权操作尝试 |
404 Not Found | 资源不存在 | URL 错误或请求的业务实体不存在 |
429 Too Many Requests | 限流 | 由网关 Sentinel 触发;通常直接由网关返回 |
5xx — 服务端错误(后端必须修复;监控必须告警)
| 码 | 含义 | 使用场景 |
|---|---|---|
500 Internal Server Error | 未处理异常 | NPE、SQL 报错、网络超时。前端展示通用文案;禁止暴露堆栈信息 |
502 / 503 / 504 | 网关/上游不可用 | 后端重启、OOM 崩溃、上游超时 |
业务码(code)规范
格式:5 位纯数字 XXYYY
0— 全局保留,表示成功。XX(前 2 位)— 服务 ID,统一分配。YYY(后 3 位)— 错误流水号,尽量与对应 HTTP 状态码对齐(如400表示参数错误,409表示冲突,500表示内部错误)。
纯数字业务码便于前端 i18n 映射,避免字符串前缀拼写错误。
服务 ID 注册表
注意:以下表格仅为示例
| 服务/模块 | 服务 ID(XX) | 码段范围 | 备注 |
|---|---|---|---|
| raf framework | 10 | 10001-10999 | 框架平台层 |
| 公共模块 | 13 | 13001-13999 | 共享工具 |
| 网关层 | 15 | 15001-15999 | 网关入口 |
| BFF 聚合层 | 17 | 17001-17999 | BFF 聚合 |
| 用户服务 | 21 | 21000-21999 | 用户 |
| 交易服务 | 25 | 25000-25999 | 交易 |
| 运营后台 | 81 | 81000-81999 | 运营 |
进阶规范
安全与数据脱敏
- 禁止在
5xx响应的message或data中暴露 SQL 语句、堆栈信息、内部 IP 或敏感字段值。 - 前端错误提示必须是通用文案(如"服务暂时不可用,请稍后重试")。开发者通过
traceId在日志系统(ELK / SkyWalking)中定位根因。
国际化(i18n)
- 后端默认返回中文
message。 - 多语言客户端中,前端不应直接渲染后端
message,而应以纯数字code(如25409)为键,在前端 i18n 包中查找对应语言的文案。 - 若后端需处理 i18n,解析请求头
Accept-Language来选择对应语言。
幂等性与重试
- 变更状态的 API(如创建订单、扣减库存)必须支持请求头
Idempotency-Key。 - 重复请求:返回
200 OK携带原始结果,或返回409 Conflict业务码。 - 这可防止网关或客户端在
5xx响应时重试导致的脏数据。