2、RESTful API 设计原则:资源导向、无状态性、统一接口、HATEOAS 概念
聊到消息接口,RESTful API 是绕不开的话题。我做了这么多年通信架构,见过太多把 REST 用成 RPC 的项目。说白了,很多人只是把 HTTP 当成了传输管道,根本没理解 REST 的精髓。
今天我就把这四个核心原则掰开揉碎了讲。你理解透了,设计出来的接口会清爽很多。
2.1 资源导向:把一切抽象为资源
REST 的核心思想是什么?是把系统中的一切视为「资源」。用户是资源,订单是资源,文章也是资源。每个资源都有一个唯一的 URI 来标识。
我个人习惯这样设计 URI:
# 好的设计
GET /users # 获取用户列表
GET /users/123 # 获取单个用户
POST /users # 创建用户
PUT /users/123 # 更新用户
DELETE /users/123 # 删除用户
# 糟糕的设计
GET /getUser?id=123
POST /createUser
POST /deleteUser?id=123
看出区别了吗?好的设计用名词表示资源,用 HTTP 方法表示操作。糟糕的设计把动词塞进了 URI 里。我在项目中遇到过团队把接口写成 /api/deleteUserById 这种风格,后来维护起来简直噩梦——接口数量爆炸,命名还不统一。
核心原则:URI 只表示资源,操作由 HTTP 方法决定。永远不要在 URI 里出现动词。
2.2 无状态性:每次请求都是独立的
无状态性是什么意思?就是服务器不保存客户端的状态。每次请求都包含所有必要的信息,服务器不需要记住你之前做过什么。
你想想看,这有什么好处?
- 水平扩展容易——任何服务器都能处理任何请求
- 故障恢复简单——挂了一台,换一台照样干活
- 缓存友好——请求独立,缓存策略清晰
嗯,这里要注意。无状态不是说应用不能有状态,而是说服务器不保存会话状态。状态可以放在客户端,比如用 Token 或 JWT。
// 有状态的请求(错误示范)
GET /api/orders
// 服务器需要知道当前用户是谁,依赖之前的登录状态
// 无状态的请求(正确示范)
GET /api/orders
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
// 每次请求都带上认证信息,服务器无需记忆
我曾经踩过一个坑。早期做电商系统,把用户购物车信息存在服务器 Session 里。结果用户量一上来,服务器扛不住,加机器又因为 Session 不共享导致用户数据错乱。后来改成无状态设计,把购物车信息存在客户端,每次请求都带上,问题就解决了。
避坑指南:我曾经在无状态接口里偷偷用了服务端缓存来存用户状态,结果上线后用户数据串得一塌糊涂。无状态就是无状态,别耍小聪明。
2.3 统一接口:用标准化的方式操作资源
统一接口的意思是,所有资源都通过相同的接口规范来操作。HTTP 方法就是这套规范的核心。
| HTTP 方法 | 操作 | 幂等 | 安全 |
|---|---|---|---|
| GET | 获取资源 | 是 | 是 |
| POST | 创建资源 | 否 | 否 |
| PUT | 完整更新资源 | 是 | 否 |
| PATCH | 部分更新资源 | 否 | 否 |
| DELETE | 删除资源 | 是 | 否 |
统一接口还要求使用标准的 HTTP 状态码。200 表示成功,201 表示创建成功,404 表示资源不存在,500 表示服务器内部错误。别自己发明状态码,也别把错误信息全塞在 200 里。
小技巧:我习惯在响应体里统一返回 { "code": 0, "message": "success", "data": {...} } 这种结构。HTTP 状态码管传输层,业务状态码管应用层,两者不冲突。
2.4 HATEOAS:让 API 自描述
HATEOAS 全称是 Hypermedia as the Engine of Application State。名字很唬人,说白了就是:API 返回的数据里,应该包含下一步能做什么的链接。
举个例子你就明白了:
// 传统 API 返回
{
"orderId": 123,
"status": "pending",
"amount": 99.00
}
// 带 HATEOAS 的返回
{
"orderId": 123,
"status": "pending",
"amount": 99.00,
"links": [
{ "rel": "self", "href": "/orders/123" },
{ "rel": "pay", "href": "/orders/123/payments", "method": "POST" },
{ "rel": "cancel", "href": "/orders/123", "method": "DELETE" }
]
}
看到区别了吗?传统 API 返回的是死数据,客户端得自己硬编码下一步逻辑。HATEOAS 把「能做什么」也告诉你了。客户端只需要跟着链接走,不需要提前知道所有接口地址。
我个人觉得,HATEOAS 在实际项目中用得不多,但它的思想很有价值。它让 API 变得可发现、可演化。你想想看,如果哪天接口地址变了,只要链接对,客户端根本不需要改代码。
我的建议:不用追求完全的 HATEOAS 实现,但可以在关键资源上加上 links 字段。比如订单详情里带上支付链接,用户信息里带上修改密码的链接。这样 API 的可用性会好很多。
2.5 知识体系总览
下面这张图把四个原则的关系梳理清楚了。你看一眼就能把握整体脉络。
这四个原则不是孤立的。资源导向决定了你用什么来抽象系统,无状态性决定了请求怎么交互,统一接口规范了操作方式,HATEOAS 让 API 变得智能。把它们结合起来,你就能设计出真正符合 REST 精神的接口。
好了,这一章就到这里。记住,设计 RESTful API 不是套模板,而是理解背后的思想。下次你写接口的时候,多想想这四个原则,代码质量会提升不少。