2. REST API 基础:RESTful 架构风格定义、资源导向设计、HTTP 方法与状态码

2.1 RESTful 架构风格定义

REST(Representational State Transfer,表述性状态转移)是由 Roy Fielding 在 2000 年博士论文中提出的一种架构风格,而非具体协议或标准。其核心思想是将网络中的一切视为资源,并通过统一的接口对资源进行无状态操作。

关键理解:REST 不是一种技术,而是一组设计约束。符合这些约束的接口被称为 RESTful API。

RESTful 架构的六大约束条件:

  1. 客户端-服务器(Client-Server):分离关注点,客户端不关心数据存储,服务器不关心用户界面。
  2. 无状态(Stateless):每个请求包含所有必要信息,服务器不保存客户端上下文。
  3. 可缓存(Cacheable):响应隐式或显式标记为可缓存或不可缓存,提升网络效率。
  4. 统一接口(Uniform Interface):通过标准方法操作资源,简化架构。
  5. 分层系统(Layered System):客户端无法直接感知是否与端服务器或中间层通信。
  6. 按需代码(Code on Demand,可选):服务器可向客户端传输可执行代码(如 JavaScript)。
RESTful 六大约束架构图 RESTful 架构六大约束 RESTful 架构风格 ① 客户端-服务器 ② 无状态 ③ 可缓存 ④ 统一接口 ⑤ 分层系统 ⑥ 按需代码(可选) 核心:统一接口是 REST 区别于其他 RPC 风格的关键,通过标准 HTTP 方法操作资源 无状态约束保证了水平扩展能力,每个请求独立处理

2.2 资源导向设计(Resource-Oriented Design)

资源导向设计是 RESTful API 的核心设计范式。每个资源通过 URI(统一资源标识符) 唯一标识,资源的表现形式(JSON/XML/HTML)通过 Content-Type 协商确定。

资源设计原则:
  • 使用名词而非动词命名资源:/users 而非 /getUsers
  • 使用复数形式表示集合:/orders、/products
  • 使用层级结构表达资源关系:/users/{userId}/orders/{orderId}
  • 使用查询参数进行过滤、排序、分页:/users?role=admin&page=1&size=20

典型资源 URI 设计示例:

资源类型 URI 模式 说明
集合资源 /users 用户列表
单例资源 /users/{id} 单个用户详情
子集合资源 /users/{id}/orders 用户的订单列表
子资源 /users/{id}/orders/{orderId} 用户的某个订单
操作资源 /users/{id}/activate 用户激活(特殊情况使用动词)
常见反模式:避免在 URI 中使用动词(/createUser)、避免在 URI 中表达版本号(/v1/users 应通过请求头或 URL 前缀处理)、避免过深的嵌套(超过 3 层建议扁平化)。

2.3 HTTP 方法(GET/POST/PUT/DELETE)与语义

RESTful API 通过标准 HTTP 方法对资源执行 CRUD(创建、读取、更新、删除)操作。每个方法具有明确的幂等性和安全性语义。

HTTP 方法 CRUD 语义 幂等性 安全性 请求体 响应体
GET 读取资源 ✅ 是 ✅ 是 无 资源表示
POST 创建资源 ❌ 否 ❌ 否 资源数据 新资源 / 操作结果
PUT 全量更新 / 替换 ✅ 是 ❌ 否 完整资源数据 更新后的资源
DELETE 删除资源 ✅ 是 ❌ 否 无 删除状态 / 空
PATCH 部分更新 ❌ 否 ❌ 否 部分字段数据 更新后的资源
幂等性解释:多次执行同一操作,结果与执行一次相同。例如,DELETE /users/123 无论执行 1 次还是 10 次,最终资源状态都是“已删除”。POST 每次执行都会创建新资源,因此不幂等。

实际 API 调用示例:

// 获取用户列表
GET /users
Response 200:
[
  { "id": 1, "name": "Alice", "email": "alice@example.com" },
  { "id": 2, "name": "Bob", "email": "bob@example.com" }
]

// 创建新用户
POST /users
Request Body: { "name": "Charlie", "email": "charlie@example.com" }
Response 201:
{ "id": 3, "name": "Charlie", "email": "charlie@example.com" }

// 全量更新用户
PUT /users/3
Request Body: { "name": "Charlie Updated", "email": "charlie.new@example.com" }
Response 200:
{ "id": 3, "name": "Charlie Updated", "email": "charlie.new@example.com" }

// 删除用户
DELETE /users/3
Response 204: (No Content)

2.4 HTTP 状态码(Status Codes)

HTTP 状态码是服务器对请求处理结果的标准化响应。RESTful API 应使用精确的状态码表达操作结果,而非统一返回 200。

HTTP 状态码分类与常用码值 HTTP 状态码分类与常用码值 1xx 信息性 100 Continue 2xx 成功 200 OK / 201 Created 3xx 重定向 301 Moved / 304 Not Modified 4xx 客户端错误 400 Bad Request 5xx 服务器错误 500 Internal Server Error RESTful API 常用状态码速查表 • 200 OK:GET 请求成功,返回资源 • 201 Created:POST 创建资源成功,返回 Location 头 • 204 No Content:DELETE 成功 / PUT 成功无返回体 • 400 Bad Request:请求参数错误 / 校验失败 • 404 Not Found:资源不存在 / 路径错误 • 409 Conflict:资源冲突(如唯一约束) • 422 Unprocessable Entity:语义错误 • 429 Too Many Requests:限流触发 • 500 Internal Server Error:服务器内部异常 • 503 Service Unavailable:服务暂不可用

2.5 完整请求-响应流程示例

以下展示一个完整的 RESTful API 交互流程,涵盖资源创建、查询、更新和删除:

// 1. 创建订单(POST)
POST /orders
Content-Type: application/json
{
  "userId": 1,
  "items": [
    { "productId": 101, "quantity": 2 },
    { "productId": 202, "quantity": 1 }
  ]
}
Response: 201 Created
Location: /orders/1001
{
  "id": 1001,
  "userId": 1,
  "status": "pending",
  "total": 299.99,
  "createdAt": "2025-01-15T10:30:00Z"
}

// 2. 查询订单(GET)
GET /orders/1001
Response: 200 OK
{
  "id": 1001,
  "userId": 1,
  "status": "pending",
  "items": [
    { "productId": 101, "name": "Widget A", "quantity": 2, "price": 99.99 },
    { "productId": 202, "name": "Gadget B", "quantity": 1, "price": 100.01 }
  ],
  "total": 299.99
}

// 3. 更新订单状态(PATCH)
PATCH /orders/1001
Content-Type: application/json
{ "status": "shipped" }
Response: 200 OK
{
  "id": 1001,
  "status": "shipped",
  "updatedAt": "2025-01-15T11:00:00Z"
}

// 4. 删除订单(DELETE)
DELETE /orders/1001
Response: 204 No Content
最佳实践总结:
  • 始终使用名词复数作为集合资源 URI
  • 严格遵循 HTTP 方法的语义,不要用 GET 修改资源状态
  • 返回精确的状态码,避免统一返回 200 然后在 body 中包装错误
  • 使用 Location 头返回新创建资源的 URI(201 响应)
  • 对集合资源支持分页、过滤、排序(通过查询参数)
  • 使用 HATEOAS(超媒体作为应用状态引擎)提供资源导航链接(可选但推荐)