后端开发
RESTful API 设计最佳实践:从资源建模到版本演进
{}
REST 的核心:资源
REST 把系统抽象成资源(名词),用 HTTP 方法(动词)表达操作。设计得好不好,先看 URL 一眼就能判断。
资源建模规范
# 命名:复数名词 + 小写 + 中划线
GET /api/users # 列表
POST /api/users # 创建
GET /api/users/42 # 单个
PATCH /api/users/42 # 部分更新
DELETE /api/users/42 # 删除
# 子资源:层级关系
GET /api/users/42/orders # 用户的订单
GET /api/users/42/orders/7 # 用户的某个订单
# 动作型操作:用子资源或自定义端点表达
POST /api/orders/7/cancel # 取消订单(非动词化:/api/cancelOrder ✗)
避免在 URL 里放动词(/getUserData、/deleteOrder 都是反模式)。
HTTP 方法语义与状态码
方法 语义 成功响应 场景
GET 读 200/206 查询列表、详情
POST 新建 201 + Location 创建资源
PUT 全量替换 200 完整覆盖
PATCH 部分更新 200 只改个别字段
DELETE 删除 204 幂等删除
# 常见错误码
400 参数错误 401 未认证 403 无权限
404 不存在 409 冲突 429 限流
422 校验失败 500 服务端异常
原则:语义要精确 -- 未登录返回 401 而非 403;资源不存在返回 404 而非 500。
分页:offset 还是 cursor?
# offset 分页(简单,但深翻页慢)
GET /api/articles?page=3&size=20
GET /api/articles?offset=40&limit=20
# cursor 分页(推荐,稳定且快)
GET /api/articles?cursor=eyJpZCI6MTAwfQ&limit=20
# 返回:{ "data": [...], "next_cursor": "..." }
列表数据量大且不断变化时,offset 翻页会出现重复/遗漏,cursor(游标,基于排序字段)才是正解。
统一错误结构
{
"code": 42201, // 业务错误码,前端可直接判断
"message": "手机号格式不正确",
"field": "phone", // 字段级错误定位
"request_id": "a1b2c3" // 日志追踪
}
错误响应必须结构化,别只丢一行字符串。配合 request_id,线上排障效率翻倍。
版本与幂等
- 版本:用 URL 前缀
/api/v1/或请求头Accept: application/vnd.api+json;version=1,破坏性变更必须升版本 - 幂等:POST 创建用
Idempotency-Key请求头,重试不产生重复订单/支付 - 字段裁剪:支持
?fields=id,title与?include=author,避免超载响应
REST API 是团队间的"接口契约" -- 命名一致、语义精确、错误可读,就是最好的文档。