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就是资源的地址。

我建议你记住几个原则:

  1. 用名词,不用动词/customers 而不是 /getCustomers
  2. 用复数形式/orders 而不是 /order
  3. 层级关系用斜杠表示/customers/123/orders
  4. 查询参数用于过滤和排序/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的哲学。理解了它背后的思想,你设计出来的接口自然就好用、好维护。