做后端开发这些年,我见过太多「看起来很美」的 API,写出来却让人想骂街。有的返回 200 实际是错误,有的命名全靠猜,有的文档写得天花乱坠一跑起来全是 bug。今天不整虚的,咱就聊聊 RESTful API 设计里那些容易被忽略但巨坑的细节。
1. 状态码:你真的会用吗?
最离谱的见过什么?返回 200 状态码,body 里写着 {"code": 500, "message": "服务器内部错误"}。我当时就???这不纯属糊弄人吗?
HTTP 状态码是给人看的,不是给你偷懒用的。正确姿势:
- 200 - 一切正常,返回你期望的数据
- 201 - 创建成功(POST 返回这个,比 200 讲究)
- 400 - 你的请求有问题,比如参数校验失败
- 401 - 没认证,先登录去
- 403 - 认证了但没权限,别挣扎
- 404 - 资源不存在,不是「用户不存在」就是「订单不存在」
- 500 - 我们的锅,但这种错误一般不要让用户看到详情
有个原则:能用状态码表达的意思,别放到 body 里。你要是连状态码都懒得设对,那你写的 API 迟早被人吐槽到自闭。
2. 命名:拼音 vs 英文?都不对!
见过用拼音命名的 API 吗?/api/getUserInfoById 这种?每次调用都觉得自己在用老年机。拼音命名是上世纪的遗产,英文才是正道。
但纯英文也不一定对。很多人喜欢走极端:
// 过度设计型
GET /api/v1/users/{user_id}/account-settings/preferences/notifications/sms
// 随意型
GET /api/getUser
POST /api/setUser
// 正常型
GET /api/users/{id}
PATCH /api/users/{id}
RESTful 的精髓是「名词优先」,动词用 HTTP 方法表达。别搞什么 getUser、deleteUser、updateUser 一股脑全堆在 URL 里。资源是复数形式,路径结构要扁平。
有个小技巧:你的 URL 应该能猜出来。新来的同事看了你的 API 文档,能猜到某个功能的接口大概长什么样,这就是好的设计。
3. 分页:最容易翻车的地方
「这个接口怎么返回这么多数据?」——十有八九是分页没做好。分页是个看起来简单实际上巨坑的功能。
常见的分页方式:
// 偏移分页(最常见,但有性能问题)
GET /api/users?page=1&page_size=20
// 游标分页(适合大数据量,性能稳定)
GET /api/users?cursor=eyJpZCI6MTAwfQ&limit=20
// 区间分页(适合需要快速跳转的场景)
GET /api/users?offset=0&limit=20
偏移分页的坑:当你有 100 万条数据,查询第 99 万条起的前 20 条,数据库要扫描前面 99 万条才能给你返回。这种场景下,游标分页才是正确答案。
分页返回格式也要规范:
{
"data": [...],
"pagination": {
"total": 1000000,
"page": 1,
"page_size": 20,
"has_next": true
}
}
别返回这种:[1, 2, 3, 4, 5, ...] 然后让我猜有多少条。
4. 错误处理:让人能看懂的那种
错误处理是 API 的脸面。很多接口返回的错误让人摸不着头脑:
// 这种错误消息等于没说
{
"error": "Invalid parameter"
}
// 这种才叫有诚意
{
"error": {
"code": "VALIDATION_FAILED",
"message": "请求参数校验失败",
"details": [
{"field": "email", "message": "邮箱格式不正确"},
{"field": "age", "message": "年龄必须大于0"}
]
}
}
错误码比错误消息更重要。消息给人看,错误码给程序看。你要是每次错误都只返回一个「操作失败」,调用方根本没法自动化处理。
还有一点:错误消息不要暴露内部细节。你要是把 SQL 错误、堆栈信息直接返回出去,不是给人学习的机会,是给黑客敞开大门。
5. 版本控制:早做早超生
「接口要兼容旧版本吗?」「不加版本号行不行?」——每次有人问这种问题,我就知道他们迟早要踩这个坑。
版本控制的三种主流方式:
// URL 路径版本(最直观,GitHub 在用)
GET /api/v1/users
GET /api/v2/users
// Header 版本(Clean URL,但容易被忽略)
GET /api/users
Accept: application/vnd.api+json; version=2
// Query 参数版本(简单但不推荐)
GET /api/users?version=2
我的建议:用 URL 路径版本。简单粗暴,调试方便,一眼就能看出调用的是哪个版本。别觉得丑,好用才是硬道理。
版本迭代的时候,不要删除旧版本,至少保留 6-12 个月。给调用方足够的时间迁移。你要是上午发版下午就下线旧版,等待你的是连环夺命 call。
6. 安全性:别等被刷了再后悔
API 安全是个老生常谈但总被忽视的话题。几个必须要注意的点:
- 限流(Rate Limiting):没限流的 API 就是裸奔。一个接口一天被调几十万次,服务器说挂就挂。
- 参数校验:后端必须校验所有输入,别相信前端传的任何一个参数。
- 敏感数据:密码、token 这种东西,绝对不能出现在 URL 参数里(会被日志出卖)。
- CORS:跨域配置要严谨,别
*一把梭。
总结
好的 API 设计不是什么高深莫测的东西,核心就一句话:让人用着舒服、出错了能快速定位、安全性不掉链子。
你写的 API 就是你的名片。下次接手别人写的 API,你希望看到什么样的?是结构清晰、错误明确、文档齐全?还是满屏 map<String,Object>、状态码永远 200、错误消息永远「系统繁忙」?
己所不欲,勿施于人。共勉。