【计算机通识】认识 RESTful API

RESTful API 不仅是一套规则,更是一种哲学和设计风格

1. 什么是 RESTful API?

首先,我们需要理解两个核心概念:

  • REST : 表述性状态转移 ,由 Roy Fielding 博士在其博士论文中提出。它是一种软件架构风格,而不是标准。它是一组设计原则和约束条件,基于 HTTP 协议。
  • RESTful API: 符合 REST 架构风格设计的 API。我们可以理解为 "REST 式的 API"。

简单来说,RESTful API 将网络上的所有事物(数据、服务)都抽象为资源。我们通过统一的接口(HTTP 方法)对资源进行操作,从而实现客户端与服务器的交互。


2. REST 的核心架构约束(六大原则)

要真正理解 RESTful,必须了解其背后的六个约束。满足这些约束的 API 才能称为 "RESTful"。

  1. 客户端-服务器: 关注点分离。客户端负责用户界面和用户体验,服务器负责数据存储、业务逻辑和安全。两者可以独立演化。
  2. 无状态 : 这是最关键的原则之一。 每个来自客户端的请求必须包含服务器处理该请求所需的所有信息。服务器不应存储任何客户端上下文。会话状态完全由客户端负责(例如,通过 Token)。
    • 好处: 可伸缩性高,服务器无需维护状态,可以轻松部署到集群。
    • 坏处: 每次请求可能需要携带更多重复数据(如认证 Token)。
  3. 可缓存: 响应必须明确标示自己是否可缓存,以防止客户端获取过期或不恰当的数据。这可以大大提高性能。
  4. 统一接口 : 这是 REST 系统设计的核心。它简化了架构,解耦了各个部分。具体包括:
    • 资源的标识(URI)
    • 通过表述对资源执行操作(JSON, XML)
    • 自描述消息
    • 超媒体作为应用状态引擎(HATEOAS)
  5. 分层系统: 系统可以由多个层次组成,每个层次只知道相邻的层次。这提高了系统的可扩展性和安全性。例如,你可以在客户端和服务器之间加入负载均衡器、网关、防火墙等,而客户端无需知道这些细节。
  6. 按需代码(可选): 服务器可以临时向客户端传输逻辑代码(如 JavaScript),供客户端执行。这是唯一一个可选的约束。

3. RESTful API 设计最佳实践(具体怎么做)

现在,我们抛开理论,看看在实际开发中如何设计一个优秀的 RESTful API。

3.1. 面向资源设计 URI

URI 的核心是标识资源,而不是动作。

  • 使用名词,而非动词:

    • 不推荐 : /getUsers, /createOrder, /deleteProduct/123
    • 推荐 : GET /users, POST /orders, DELETE /products/123
  • 资源使用复数名词:

    • GET /users (获取所有用户)
    • GET /users/123 (获取 ID 为 123 的用户)
  • 使用嵌套结构表达关联关系:

    • GET /users/123/orders (获取用户 123 的所有订单)
    • GET /users/123/orders/456 (获取用户 123 的 ID 为 456 的订单)
  • 使用连字符 - 提高可读性,避免下划线 _:

    • GET /published-articles (而非 /published_articles)
  • 使用小写字母:

    • GET /users (而非 /Users)

3.2. 正确使用 HTTP 方法(动词)

HTTP 方法定义了要对资源执行的操作,这是 "统一接口" 的关键。

HTTP 方法 描述 对应 SQL 幂等性 安全性
GET 获取资源(一个或多个) SELECT
POST 创建新资源 INSERT
PUT 完整更新资源(客户端提供完整资源) UPDATE
PATCH 部分更新资源(客户端提供要修改的字段) UPDATE
DELETE 删除资源 DELETE

重要概念解释:

  • 幂等性 : 无论执行多少次,效果都一样。GET, PUT, DELETE 是幂等的。例如,多次 DELETE /users/123,结果都是用户 123 被删除。
  • 安全性 : 不改变服务器状态。只有 GET 是安全的。

示例:

  • GET /users -> 200 OK (用户列表)
  • POST /users (Body: 用户信息) -> 201 Created (创建成功)
  • GET /users/123 -> 200 OK (用户 123 的详情)
  • PUT /users/123 (Body: 完整的用户信息) -> 200 OK (更新成功)
  • PATCH /users/123 (Body: {"name": "新名字"}) -> 200 OK (部分更新成功)
  • DELETE /users/123 -> 204 No Content (删除成功,无返回体)

3.3. 合理利用 HTTP 状态码

状态码用于告知客户端请求的结果。不要在所有响应中都返回 200 OK,然后在 Body 里说明错误。

  • 2xx 成功:

    • 200 OK - 通用成功状态。
    • 201 Created - 资源创建成功。响应头 Location 应包含新资源的 URI。
    • 204 No Content - 请求成功,但无内容返回(如 DELETE 成功)。
  • 4xx 客户端错误:

    • 400 Bad Request - 通用客户端错误,服务器无法理解请求(如参数错误)。
    • 401 Unauthorized - 未认证,需要身份验证。
    • 403 Forbidden - 服务器理解请求,但拒绝授权(认证成功但权限不足)。
    • 404 Not Found - 资源不存在。
    • 405 Method Not Allowed - 不允许的 HTTP 方法。
    • 409 Conflict - 请求与当前服务器状态冲突(如修改旧版本数据)。
  • 5xx 服务器错误:

    • 500 Internal Server Error - 通用服务器错误。

3.4. 返回统一的 JSON 响应体

即使出错,也应返回结构化的 JSON 数据。

成功响应:

json 复制代码
{
  "code": 200,
  "message": "success",
  "data": {
    "id": 123,
    "name": "张三",
    "email": "zhangsan@example.com"
  }
  // 可以加入分页信息等
  // "pagination": { ... }
}

错误响应:

json 复制代码
{
  "code": 404,
  "message": "用户不存在",
  "timestamp": "2023-10-25T10:30:00Z",
  "path": "/api/v1/users/999",
  "details": "更多错误细节..."
}

3.5. 提供 API 版本管理

API 会演化,必须进行版本控制,避免破坏现有客户端。

  • URI Path 方式(最常用):

    • GET /api/v1/users
    • GET /api/v2/users
  • Query Parameter 方式:

    • GET /api/users?version=1
  • HTTP Header 方式:

    • GET /api/users
    • Headers: Accept: application/vnd.myapi.v1+json

推荐使用 URI Path 方式,因为它最直观、最简单。

3.6. 数据过滤、排序、搜索和分页

对于集合资源,这些功能是必不可少的。

  • 过滤 : GET /users?role=admin&status=active
  • 搜索 : GET /users?name=张 (模糊搜索名字中含 "张" 的用户)
  • 排序 : GET /users?sort=-created_at,username (- 表示降序)
  • 分页 : GET /users?page=2&limit=20GET /users?offset=20&limit=20

3.7. 安全性

  • 始终使用 HTTPS
  • 身份认证 : 使用标准方案,如 JWT (JSON Web Tokens)、OAuth 2.0。Token 通常通过 Authorization 请求头传递:Authorization: Bearer <token>
  • 授权: 确保用户只能访问其权限范围内的资源。
  • 限流 : 防止 API 被滥用,应返回 429 Too Many Requests

3.8. 超媒体 API (HATEOAS)

这是 REST 最高级的约束,但实践中并不总是被实现。它使 API 变得"可发现"。

在响应中提供相关资源的链接:

json 复制代码
{
  "id": 123,
  "name": "张三",
  "links": [
    {
      "rel": "self",
      "href": "/api/v1/users/123",
      "method": "GET"
    },
    {
      "rel": "orders",
      "href": "/api/v1/users/123/orders",
      "method": "GET"
    },
    {
      "rel": "update",
      "href": "/api/v1/users/123",
      "method": "PUT"
    }
  ]
}

客户端可以通过解析这些 links 来导航整个应用,而无需硬编码 URI 结构。


总结:一个好的 RESTful API 是什么样的?

一个优秀的、符合规范的 RESTful API 应该具备以下特点:

  1. 直观的: URI 清晰明了,使用名词标识资源。
  2. 语义化的: 正确使用 HTTP 方法和状态码。
  3. 一致的: 响应格式、错误处理、命名规则在整个 API 中保持一致。
  4. 无状态的: 不依赖服务器端的会话。
  5. 健壮的: 能妥善处理各种异常和错误。
  6. 安全的: 使用 HTTPS、适当的认证和授权机制。
  7. 可维护和可扩展的: 通过版本控制来管理迭代。
相关推荐
青鱼入云7 小时前
介绍一下Ribbon
后端·spring cloud·ribbon
雾岛听风来7 小时前
Android开发中常用高效数据结构
前端·javascript·后端
IT_陈寒7 小时前
Vue 3性能优化实战:这5个Composition API技巧让你的应用快30%
前端·人工智能·后端
菜鸟的迷茫7 小时前
Feign 超时 + 重试引发雪崩:一次线上事故复盘
java·后端
milanyangbo7 小时前
谁生?谁死?从引用计数到可达性分析,洞悉GC的决策逻辑
java·服务器·开发语言·jvm·后端·算法·架构
IT_陈寒7 小时前
Vue3性能翻倍的5个秘密:从Composition API到Tree Shaking实战指南
前端·人工智能·后端
IT_陈寒7 小时前
JavaScript 性能优化:3个V8引擎隐藏技巧让你的代码提速50%
前端·人工智能·后端
今日说"法"7 小时前
Rust API 设计中的零成本抽象原则:从原理到实践的平衡艺术
开发语言·后端·rust
IT果果日记7 小时前
给DataX配置加密的方法
大数据·数据库·后端