3、认识RESTful API:REST架构风格详解,资源与URI设计,无状态性与幂等性,HATEOAS概念简介
好,咱们进入第三讲。这一章可以说是整个CRM集成课的基石——RESTful API。说实话,我见过太多团队在API设计上踩坑,最后导致集成成本翻倍。今天咱们就把REST的核心掰开揉碎了讲清楚。
3.1 REST架构风格:它到底在讲什么?
REST,全称是Representational State Transfer,翻译过来叫“表述性状态转移”。名字挺拗口,但说白了,它就是一种设计Web API的架构风格,不是协议,也不是标准。
我个人习惯把REST理解为:用HTTP协议做正确的事。你想想看,HTTP本身就有GET、POST、PUT、DELETE这些方法,还有状态码、请求头、响应体。REST就是教你怎么用这些现成的东西,把系统间的交互变得优雅。
REST有六个核心约束,我挑三个最重要的讲:
- 客户端-服务器分离:前端只管展示,后端只管数据。各司其职。
- 无状态性:每个请求都包含所有必要信息,服务器不存客户端上下文。
- 统一接口:用标准化的方式操作资源,包括URI、HTTP方法、状态码。
重要:REST不是“URL里写动词”或者“所有接口都用POST”。我见过太多自称REST的API,实际上只是RPC披了层HTTP的外衣。
3.2 资源与URI设计:命名是门艺术
在REST里,一切皆资源。客户、订单、产品、合同……都是资源。URI就是资源的地址。
我建议你记住几个原则:
- 用名词,不用动词:
/customers而不是/getCustomers - 用复数形式:
/orders而不是/order - 层级关系用斜杠表示:
/customers/123/orders - 查询参数用于过滤和排序:
/orders?status=active&page=1
举个例子,CRM里常见的资源设计:
# 好的设计
GET /customers # 获取客户列表
GET /customers/123 # 获取单个客户
POST /customers # 创建客户
PUT /customers/123 # 全量更新客户
PATCH /customers/123 # 部分更新客户
DELETE /customers/123 # 删除客户
# 不好的设计
GET /getCustomerById?id=123
POST /createCustomer
POST /updateCustomer
POST /deleteCustomer
提示:我曾经在一个项目里看到有人把API设计成 /api/v1/getCustomerData,结果后面需求变了,又加了个 /api/v1/getCustomerDataV2。嗯,这种命名方式,维护起来真的很痛苦。
3.3 无状态性与幂等性:两个容易混淆的概念
这两个概念经常被放在一起说,但其实是两码事。
无状态性
无状态性要求每个请求都包含服务器处理所需的所有信息。服务器不会在请求之间保存任何客户端状态。
举个例子:
- 有状态:你先POST登录,服务器给你一个session ID,后续请求带着这个ID,服务器记得你是谁。
- 无状态:每个请求都带着完整的认证信息(比如JWT token),服务器不存session。
为什么REST要强调无状态?因为无状态才能水平扩展。你想想看,如果服务器存了session,那用户每次请求都得打到同一台机器上,负载均衡就不好做了。
注意:无状态不是说系统不能有状态。用户登录后的权限、购物车内容这些状态数据,可以存在客户端(比如token里)或者专门的缓存层(比如Redis),而不是存在应用服务器上。
幂等性
幂等性是指:同一个请求执行一次和执行多次,结果是一样的。
HTTP方法中:
| HTTP方法 | 是否幂等 | 说明 |
|---|---|---|
| GET | 是 | 多次查询同一资源,结果不变 |
| PUT | 是 | 多次更新同一资源,最终状态一致 |
| DELETE | 是 | 多次删除,第一次成功,后续返回404 |
| POST | 否 | 多次创建,会生成多个资源 |
| PATCH | 不一定 | 取决于实现,建议设计成幂等的 |
我曾经在集成一个支付系统时遇到过问题:网络超时导致重复提交,结果用户被扣了两次钱。后来我们在订单创建接口里加了幂等键(Idempotency-Key),同一个请求ID只处理一次。这个坑,踩过一次就记住了。
关键:在CRM系统里,幂等性特别重要。比如创建客户、提交订单、更新合同,这些操作如果因为网络重试导致重复执行,后果很严重。我建议你在设计API时,对POST方法也考虑幂等性,用请求ID去重。
3.4 HATEOAS概念简介:API的自我描述
HATEOAS,全称是Hypermedia As The Engine Of Application State。名字很长,但概念其实很简单:API响应里应该包含下一步可以做什么的链接。
举个例子,传统API返回:
{
"customerId": 123,
"name": "张三",
"email": "zhangsan@example.com"
}
加了HATEOAS之后:
{
"customerId": 123,
"name": "张三",
"email": "zhangsan@example.com",
"links": [
{
"rel": "self",
"href": "/customers/123"
},
{
"rel": "orders",
"href": "/customers/123/orders"
},
{
"rel": "update",
"href": "/customers/123",
"method": "PUT"
}
]
}
看到区别了吗?客户端不需要硬编码URL,而是通过响应里的链接来导航。说白了,API自己告诉你怎么用。
提示:在实际项目中,我很少看到完全遵循HATEOAS的API。因为它会增加响应体大小,而且客户端处理起来也复杂。但我会在关键资源上加上 self 和关联资源的链接,这样至少给调用方一个清晰的导航。
3.5 小结:REST在CRM集成中的实际应用
好了,咱们把REST的核心概念过了一遍。总结一下:
- 资源设计:用名词、复数、层级结构,别在URI里写动词
- 无状态性:每个请求自包含,方便水平扩展
- 幂等性:GET、PUT、DELETE天然幂等,POST要自己实现去重
- HATEOAS:让API自我描述,但实际项目中适度使用
下一章,咱们会深入讲HTTP方法、状态码和请求头,这些都是你写代码时天天要打交道的东西。到时候我会分享一些我在CRM项目里实际踩过的坑,比如状态码用错了导致前端解析失败,或者请求头没处理好导致跨域问题。嗯,到时候细说。
一句话记住:REST不是写代码的规则,而是设计API的哲学。理解了它背后的思想,你设计出来的接口自然就好用、好维护。