🎯 核心问题

前后端如何高效对话? 这就像问:餐厅的菜单怎么设计,客人一看就懂?服务员怎么记单,不会出错?上菜怎么规范,客人满意?API 设计解决的就是"对话规则"的问题。


0. 先问一个问题:你有没有经历过这些噩梦?

场景一:接口命名随心所欲

  GET /getUserData
GET /fetchUserInfo
GET /queryUserById
GET /users/query
  

四个接口,功能一样,命名风格完全不同。新人入职一脸懵:我该用哪个?

场景二:错误处理五花八门

  // 有的返回 HTTP 状态码
HTTP/1.1 404 Not Found

// 有的返回 200 + code
HTTP/1.1 200 OK
{ "code": 404, "message": "用户不存在" }

// 有的直接抛异常
HTTP/1.1 200 OK
{ "error": "出错了" }
  

前端不知道该怎么判断请求是否成功。

场景三:响应结构千人千面

  // 接口 A
{ "data": { ... } }

// 接口 B
{ "result": { ... } }

// 接口 C
{ "content": { ... } }
  

每个接口返回格式都不一样,前端需要针对每个接口单独处理。


好的 API 设计就像餐厅的点餐系统——菜单清晰、流程规范、出错有提示。


1. 什么是 API?

API(Application Programming Interface,应用程序编程接口)就是"程序之间对话的约定"。

1.1 用餐厅来类比

餐厅角色 对应概念 说明
菜单 API 文档 告诉你有哪些"菜"可以点
服务员 HTTP 协议 标准化的"对话方式"
后厨 服务端 按"订单"处理请求
上菜 响应 把结果返回给"客人"

1.2 一个完整的 API 请求

👇 动手试试看:点击下方按钮,观察一次完整的 API 请求-响应流程:


2. API 设计哲学:RPC / REST / GraphQL / gRPC

在开始具体的 RESTful 设计之前,先了解四种主流的 API 设计风格:

2.1 REST vs RESTful:有什么区别?

很多人会混淆这两个概念:

概念 含义 说明
REST 一种架构风格 由 Roy Fielding 提出的设计理念,包含一组约束条件
RESTful 符合 REST 风格的 形容词,表示 API 设计遵循了 REST 原则

类比

  • REST 就像"极简主义"——一种设计理念
  • RESTful API 就像"极简风格的房间"——应用了这个理念的具体实现

REST 的六大约束

约束 说明
客户端-服务器分离 前后端独立开发,接口解耦
无状态 每个请求包含所有必要信息,服务器不保存会话状态
可缓存 响应应标明是否可缓存,提高性能
统一接口 使用标准的 HTTP 方法和状态码
分层系统 客户端无需知道连接的是哪层服务器
按需代码(可选) 服务器可以扩展客户端功能
💡 为什么 REST 最常用?
  1. 学习成本低:HTTP 协议本身就体现了 REST 思想
  2. 生态成熟:工具、框架、文档丰富
  3. 通用性强:任何语言、任何平台都能调用
  4. 易于缓存:GET 请求天然可缓存,CDN 友好

3. RESTful 设计:让 URL 会说话

REST(Representational State Transfer)是一种架构风格,核心思想是:

  • 把网络上的事物抽象为"资源"(Resource)
  • 用 URL 标识资源
  • 用 HTTP 方法操作资源

3.1 用仓库来类比

仓库概念 REST 对应 示例
货架地址 URL /users/orders
操作方式 HTTP 方法 GET(查看)、POST(入库)
货物 资源 用户数据、订单数据

关键原则:URL 是名词,不是动词。

3.2 URL 设计规则

规则 错误示例 正确示例 说明
用名词不用动词 /getUsers /users URL 表示资源,HTTP 方法表示操作
用复数形式 /user /users 统一复数风格
小写+连字符 /UserProfiles /user-profiles URL 大小写敏感
避免层级过深 /a/b/c/d/e /a/b/c 最多 3 层
过滤用查询参数 /products/phone/5000 /products?cat=phone 过滤条件用 ? 参数
💡 URL 大小写敏感

统一用小写 + 连字符(-)是最安全的做法,避免大小写混乱和下划线风格不一致的问题。

3.3 HTTP 方法选择

方法 用途 幂等性 安全性 典型场景
GET 获取资源 查询列表、查看详情
POST 创建资源 新增用户、提交订单
PUT 全量更新 替换整个用户资料
PATCH 部分更新 只修改昵称
DELETE 删除资源 删除用户、取消订单
💡 什么是幂等性?

幂等性:多次执行结果相同。

  • 幂等的操作(GET/PUT/DELETE):点 10 次和点 1 次,结果一样
  • 不幂等的操作(POST):点 10 次,可能创建 10 个订单

解决方案:POST 操作用唯一 ID 校验,避免重复处理。


4. 状态码:让错误"会说话"

HTTP 状态码是服务器告诉客户端"发生了什么"的标准方式。

4.1 状态码分类

分类 含义 典型状态码
2xx 成功 200 OK、201 Created、204 No Content
3xx 重定向 301 永久移动、304 未修改
4xx 客户端错误 400 参数错误、401 未认证、404 不存在
5xx 服务端错误 500 内部错误、503 服务不可用

4.2 常用状态码演示

👇 动手试试看:点击下方按钮,了解常见状态码的含义:


5. 错误处理:优雅地"拒绝"

好的错误处理能让客户端"看状态码就知道怎么回事",而不是去猜。

4.1 错误处理的"避坑指南"

坑 1:所有错误都返回 200

  // ❌ 错误做法
HTTP/1.1 200 OK
{ "error": "出错了" }
  

问题:缓存层会缓存这个"成功"响应,监控系统发现不了问题。

坑 2:错误信息太笼统

  // ❌ 错误做法
HTTP/1.1 400 Bad Request
{ "message": "参数错误" }
  

问题:客户端不知道哪个参数错了、为什么错。

坑 3:暴露敏感信息

  // ❌ 危险做法
HTTP/1.1 500 Internal Server Error
{ "stack": "at UserService.login...", "sql": "SELECT * FROM..." }
  

危险:暴露了代码结构、数据库查询,攻击者可以利用这些信息。

5.2 正确的错误处理演示

👇 动手试试看:对比"好的"和"差的"错误响应设计:


6. 版本控制:API 的"向后兼容"

6.1 为什么要版本控制?

场景:你的 App 有 100 万用户,需要修改订单接口。

如果不做版本控制

  • 新 App 调用新接口 → 正常
  • 旧 App 调用新接口 → 字段缺失,崩溃!

正确的做法

  • /v1/orders - 旧接口,继续服务旧 App
  • /v2/orders - 新接口,新功能在这里

6.2 版本控制策略

策略 示例 优点 缺点
URL 路径 /v1/users 直观、易缓存 URL 变长
请求头 Accept: vnd.api.v2+json URL 干净 不便调试
查询参数 /users?version=2 简单 不够标准

6.3 版本演进示例

以用户接口为例,展示 v1 到 v2 的演进:

接口 v1(旧版) v2(新版) 变化说明
获取用户 GET /v1/users
返回:name, email
GET /v2/users
返回:name, email, avatar, phone
新增头像、手机号字段
创建订单 POST /v1/orders
接收:items[]
POST /v2/orders
接收:items[], coupons[]
新增优惠券支持
批量操作 POST /v2/orders/batch 新增批量创建接口
💡 版本控制最佳实践
  • 保持向后兼容:v1 接口至少维护 6-12 个月,给客户端升级时间
  • 文档同步更新:每个版本有独立的 API 文档
  • 废弃公告:提前通知 v1 将在何时下线,引导迁移
  • 监控使用情况:统计 v1 调用量,确认可以安全下线后再停止服务

7. 响应结构设计

响应结构是前后端协作的"数据契约",统一格式能大幅降低沟通成本。

7.1 大厂实践参考

Google API 设计指南 参考 [Google API Design Guide](https://cloud.google.com/apis/design/errors),Google 要求所有 API 错误响应必须包含 `google.rpc.Status` 消息结构:
  {
  "error": {
    "code": 429,
    "message": "资源不足,请稍后重试",
    "status": "RESOURCE_EXHAUSTED",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.ErrorInfo",
        "reason": "RESOURCE_AVAILABILITY",
        "domain": "compute.googleapis.com",
        "metadata": {
          "zone": "us-east1-a",
          "service": "compute"
        }
      }
    ]
  }
}
  

核心要求

  • 必须包含 ErrorInfo 提供机器可读的错误标识
  • message 面向开发者,用简洁语言描述问题和解决方案
  • details 数组可包含 LocalizedMessage(本地化消息)、Help(帮助链接)等
Microsoft REST API 指南 参考 [Microsoft REST API Guidelines](https://github.com/microsoft/api-guidelines/blob/vNext/Guidelines.md),微软强调响应的一致性:

错误与故障的分类

  • 错误(Error):客户端传递无效数据导致,返回 4xx,不影响 API 可用性
  • 故障(Fault):服务端无法正确响应有效请求,返回 5xx,影响 API 可用性

响应标头规范

  • Date:必须返回,使用 RFC 5322 格式(GMT 时区)
  • Content-Type:必须返回
  • ETag:支持乐观并发控制的资源必须返回
阿里巴巴 Java 开发手册 参考 [阿里巴巴 Java 开发手册](https://developer.aliyun.com/special/tech-java),阿里对 API 响应有以下规范:

统一返回对象

  public class Result<!-- TODO: T START --> {
    private Integer code;
    private String message;
    private T data;
    private String requestId;
}
  

错误码分段设计

范围 类型 示例
0 成功 0
1xxxx 参数错误 10001 缺少必填参数
2xxxx 业务错误 20001 余额不足
3xxxx 认证错误 30001 未登录
5xxxx 系统错误 50001 数据库异常
Stripe API 响应设计 参考 [Stripe API Documentation](https://docs.stripe.com/api/errors),Stripe 的错误响应设计非常精细:
  {
  "error": {
    "type": "card_error",
    "code": "card_declined",
    "message": "Your card was declined.",
    "param": "number",
    "decline_code": "insufficient_funds",
    "doc_url": "https://stripe.com/docs/error-codes/card-declined"
  }
}
  

设计亮点

  • type 区分错误类型:api_errorcard_errorinvalid_request_error
  • param 指出具体哪个参数出错,前端可直接定位表单字段
  • doc_url 提供文档链接,开发者可深入了解
  • decline_code 提供更细粒度的错误原因
JSON:API 规范 参考 [JSON:API Specification](https://jsonapi.org/format/),这是一个业界广泛采纳的 JSON API 响应规范:
  {
  "data": {
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON:API 规范详解"
    },
    "relationships": {
      "author": {
        "data": { "type": "users", "id": "9" }
      }
    }
  },
  "included": [
    {
      "type": "users",
      "id": "9",
      "attributes": {
        "name": "张三"
      }
    }
  ]
}
  

核心设计

  • data 包含主资源,必须有 typeid
  • attributes 存放资源属性
  • relationships 描述资源关联
  • included 避免重复请求,一次性返回关联数据
GitHub REST API 响应设计 参考 [GitHub REST API Documentation](https://docs.github.com/en/rest),GitHub 的响应设计注重开发者体验:

成功响应

  {
  "id": 1296269,
  "node_id": "MDEwOlJlcG9zaXRvcnkxMjk2MjY5",
  "name": "Hello-World",
  "full_name": "octocat/Hello-World",
  "owner": {
    "login": "octocat",
    "id": 1,
    "avatar_url": "https://github.com/images/error/octocat_happy.gif"
  },
  "private": false,
  "html_url": "https://github.com/octocat/Hello-World"
}
  

错误响应

  {
  "message": "Bad credentials",
  "documentation_url": "https://docs.github.com/rest"
}
  

设计亮点

  • 响应包含多种 URL 格式(html_urlurl)方便不同场景使用
  • 错误响应包含 documentation_url 指向文档
  • 使用 Link 响应头实现分页导航
Twitter/X API v2 响应设计 参考 [Twitter API v2 Documentation](https://developer.twitter.com/en/docs/twitter-api),Twitter API v2 采用简洁的响应格式:
  {
  "data": {
    "id": "1460323737035677698",
    "text": "Hello, Twitter!"
  },
  "includes": {
    "users": [
      {
        "id": "2244994945",
        "name": "Twitter Dev",
        "username": "TwitterDev"
      }
    ]
  }
}
  

设计亮点

  • data 包含主数据,includes 包含关联数据(类似 JSON:API)
  • 支持字段选择:?tweet.fields=created_at,public_metrics
  • 分页使用 next_tokenprevious_token

7.2 最佳实践总结

综合以上规范,响应结构设计应遵循以下原则:

  1. 一致性优先:所有接口使用相同的响应结构,前端可统一封装请求层
  2. 机器可读:错误码 + 错误原因(reason)让程序能自动处理
  3. 人类友好:message 描述清晰,包含解决建议
  4. 可追踪:request_id 贯穿请求全链路,便于问题定位
  5. 国际化支持:通过 details 扩展本地化消息

7.3 data 字段设计规范

data 是响应的核心,其设计直接影响前端开发效率。

7.4 错误响应设计进阶


8. 实战:电商系统 API 设计示例

  # 用户模块
GET    /v1/users                    # 获取用户列表
POST   /v1/users                    # 创建新用户
GET    /v1/users/{id}               # 获取用户详情
PUT    /v1/users/{id}               # 全量更新用户
PATCH  /v1/users/{id}               # 部分更新用户
DELETE /v1/users/{id}               # 删除用户

# 订单模块
GET    /v1/users/{id}/orders        # 获取某用户的订单
POST   /v1/orders                   # 创建订单
GET    /v1/orders/{id}              # 获取订单详情
PATCH  /v1/orders/{id}/status       # 更新订单状态

# 商品模块(复杂过滤用查询参数)
GET    /v1/products?category=phone&price_max=5000&sort=price_desc&page=1
  

9. 用 AI 辅助设计 API

AI 可以帮助你快速生成符合规范的 API 设计。关键在于提供清晰的上下文和约束条件。

9.1 提示词模板

  你是一位资深的后端架构师,精通 RESTful API 设计。请帮我设计一套 API 接口。

## 业务背景
[描述你的业务场景,例如:电商系统、博客平台、任务管理等]

## 功能需求
[列出需要的功能模块,例如:
- 用户管理:注册、登录、个人信息
- 订单管理:创建订单、查询订单、取消订单
- 商品管理:商品列表、商品详情、搜索]

## 设计要求
1. 遵循 RESTful 规范
2. URL 使用名词复数,小写+连字符
3. 正确使用 HTTP 方法(GET/POST/PUT/PATCH/DELETE)
4. 统一的响应格式:{ code, message, data, request_id }
5. 合理的状态码使用
6. 版本控制:URL 路径方式(/v1/)

## 输出格式
请按以下格式输出:

### 接口列表
| 方法 | URL | 描述 | 请求体 | 响应体 |
|------|-----|------|--------|--------|

### 请求/响应示例
[关键接口的详细示例]

### 状态码说明
[使用的状态码及其含义]
  

9.2 实战示例:电商订单 API

输入提示词:

  你是一位资深的后端架构师,精通 RESTful API 设计。请帮我设计一套电商订单系统的 API 接口。

## 业务背景
一个 B2C 电商平台,用户可以浏览商品、下单购买、查看订单状态。

## 功能需求
- 订单模块:创建订单、查询订单列表、查询订单详情、取消订单、支付订单
- 购物车模块:添加商品、修改数量、删除商品、查看购物车

## 设计要求
1. 遵循 RESTful 规范
2. URL 使用名词复数,小写+连字符
3. 正确使用 HTTP 方法
4. 统一的响应格式
5. 版本控制:/v1/
  

AI 输出示例:

方法 URL 描述
POST /v1/orders 创建订单
GET /v1/orders 查询订单列表
GET /v1/orders/{id} 查询订单详情
PATCH /v1/orders/{id}/status 更新订单状态(取消/支付)
GET /v1/users/{id}/cart 获取购物车
POST /v1/users/{id}/cart/items 添加商品到购物车
PATCH /v1/users/{id}/cart/items/{itemId} 修改购物车商品数量
DELETE /v1/users/{id}/cart/items/{itemId} 删除购物车商品

9.3 AI 辅助设计的注意事项

注意点 说明
提供完整上下文 业务背景、用户角色、数据关系都要说清楚
明确约束条件 命名规范、版本策略、响应格式等要提前定义
迭代优化 第一次输出可能不完美,追问细节、要求修改
人工审核 AI 生成的内容需要人工检查是否符合业务需求
补充边界情况 让 AI 考虑错误处理、权限控制、分页等边界情况
💡 追问技巧
  • “请补充每个接口的错误响应示例”
  • “请考虑分页、排序、过滤参数”
  • “请添加接口的权限控制说明”
  • “请检查是否符合 RESTful 最佳实践”

名词速查表

名词 英文 解释
API Application Programming Interface 程序之间对话的约定
REST Representational State Transfer 一种架构风格,用 URL 标识资源
资源 Resource REST 架构的核心概念,有唯一标识(URL)
幂等性 Idempotency 多次执行结果相同
状态码 Status Code HTTP 协议定义的响应状态
版本控制 Versioning 让新旧 API 并存,平滑升级
请求体 Request Body POST/PUT/PATCH 请求携带的数据
响应体 Response Body 服务器返回的数据
Header Header 请求/响应的元数据(如 Content-Type)
认证 Authentication 验证"你是谁"(登录、Token)
授权 Authorization 验证"你能做什么"(权限)

Last updated 26 Apr 2026, 03:21 +0800 . history