重构与API设计:重构RESTful API的接口与参数
API重构这事儿,说实话比后端逻辑重构要敏感得多。你改个内部函数,大不了跑一遍单元测试。但API一旦上线,客户端、第三方、甚至你同事写的脚本都可能依赖它。改不好,就是线上事故。
我个人习惯是:先保证兼容,再谈优化。今天咱们就聊聊,怎么在不动声色的情况下,把那些丑陋的接口和参数给收拾干净。
一、接口路径的“坏味道”与重构
先看一个我接手过的真实案例。某个老系统的API长这样:
GET /getUserInfo?userId=123
POST /updateUserData
DELETE /removeUserRecord?userId=123
你发现问题了吗?动词全写在路径里了。RESTful风格讲究的是用HTTP动词表达操作,路径只应该表示资源。我见过不少团队,一开始图省事,后面越堆越乱。
重构后的版本:
GET /users/123
PUT /users/123
DELETE /users/123
嗯,这里要注意:路径重构不能直接删旧接口。你得先加新接口,等所有调用方迁移完毕,再废弃旧的。我一般会留一个过渡期,至少两个版本迭代。
二、参数设计的“坑”与填坑
参数设计是API重构里最容易出幺蛾子的地方。我曾经因为一个参数名改了个大小写,导致前端三天没睡好觉——当然,这是夸张说法,但确实很麻烦。
常见的参数问题:
- 参数名不统一:有的接口用 userId,有的用 user_id,有的用 uid
- 参数类型模糊:同一个字段,有时传字符串,有时传数字
- 可选参数过多:一个接口十几个参数,大部分都是可选的
举个例子,一个订单查询接口:
// 重构前
GET /orders?status=1&page=1&size=20&sort=time&order=desc&startDate=2024-01-01&endDate=2024-12-31&keyword=手机
这接口看着就头疼。参数一多,调用方容易漏传、错传。我的做法是:把强相关的参数打包成子资源或查询对象。
// 重构后
GET /orders?filter=status:1,dateRange:2024-01-01~2024-12-31&page=1&size=20&sort=-time
你看,我把状态和日期范围合并成了一个 filter 参数,排序也简化了(用负号表示降序)。当然,这种设计需要前后端约定好解析规则。
三、版本管理的“温柔”策略
API版本管理,说白了就是给重构留后路。我见过两种主流做法:
| 方式 | 示例 | 优点 | 缺点 |
|---|---|---|---|
| URL路径版本 | /v1/users/123 | 直观,容易路由 | 版本号污染URL |
| 请求头版本 | Accept: application/vnd.myapp.v1+json | URL干净,语义化 | 调试不方便 |
我个人习惯用URL路径版本。为什么?因为简单。你想想看,前端同学调试的时候,直接在浏览器地址栏改个版本号就能切版本,多方便。用请求头的话,还得装插件或者写脚本。
但要注意:版本号不要轻易升。每次升版本,意味着你要同时维护两套代码。我见过一个项目,v1到v5共存,光维护就累死人。我的建议是:最多同时维护两个大版本,旧版本超过半年就强制下线。
四、响应结构的“统一”之道
响应结构不统一,是API重构里最让人抓狂的问题之一。有的接口返回:
{ "code": 0, "data": { ... }, "msg": "success" }
有的接口返回:
{ "status": "ok", "result": { ... } }
还有的直接返回一个数组:
[ { "id": 1, "name": "张三" }, ... ]
你让前端怎么统一处理?每次都得写兼容代码。重构的目标就是:所有接口返回统一的结构。
{
"code": 0,
"message": "success",
"data": {
// 具体业务数据
},
"meta": {
"page": 1,
"size": 20,
"total": 100
}
}
code 表示业务状态码,0 是成功,非0是各种错误。message 给开发者看,data 放业务数据,meta 放分页等元信息。这样前端只需要写一个统一的拦截器,所有接口都能用。
五、知识体系总览
下面这张图,是我对API重构核心思路的总结。你可以把它当作一个检查清单:
这张图把API重构拆成了五个维度。路径设计是骨架,参数设计是血肉,版本管理是保险,响应结构是门面,兼容策略是底线。缺一个,重构就容易翻车。
六、实战中的“灰度”策略
最后聊点实际的。API重构不像内部代码重构,你不能“改完就上线”。我通常的做法是:
- 加新接口,不改旧接口:新功能用新接口,旧接口保持不动
- 标记废弃:在旧接口的响应里加一个 Deprecated 头,或者返回一个 warning 字段
- 监控调用量:等旧接口的调用量降到零,再考虑下线
- 发公告:提前两个版本通知调用方,给足迁移时间
我记得有一次重构用户接口,旧接口有十几个调用方。我花了整整一个迭代周期,挨个通知、协助迁移。最后旧接口下线那天,我盯着监控看了半小时,确认没有报错才松了口气。
API重构,技术难度其实不大。难的是沟通、协调、和那颗对线上环境保持敬畏的心。