API · 后端架构 / 接口规范 / 最佳实践

API 设计原则

优秀的 API 设计是后端系统的基石。从资源命名到错误处理,从认证鉴权到版本控制,系统化掌握 RESTful API 设计的最佳实践与原则,构建优雅可维护的 Web API。

10大设计原则 RESTful资源建模 3种认证方案
01

RESTful 规范

REST(Representational State Transfer)是一种架构风格,而非协议。它利用 HTTP 协议的特性来设计 Web API,强调资源导向和统一接口。

资源命名规则

使用名词复数表示资源集合,避免动词。层级关系用斜杠表示,查询参数用于过滤和排序。

// ✅ 推荐 GET /api/v1/users GET /api/v1/users/{id} POST /api/v1/users GET /api/v1/users/{id}/orders GET /api/v1/users?role=admin&page=1 // ❌ 不推荐 GET /api/getUsers POST /api/createUser GET /api/userOrders?userId=123

HTTP 方法语义

方法语义幂等安全请求体响应体
GET获取资源资源表示
POST创建资源创建内容新资源
PUT完整替换完整资源更新后资源
PATCH部分更新可设计差异字段更新后资源
DELETE删除资源空/确认

版本控制策略

推荐将版本号放在 URL 路径中(/api/v1/),便于浏览和调试。也可以通过请求头 Accept: application/vnd.example.v1+json 实现内容协商。

// URL 路径版本(推荐) GET /api/v1/users // Header 版本(内容协商) GET /api/users Accept: application/vnd.myapp.v2+json // 查询参数版本(不推荐) GET /api/users?version=1
02

HTTP 方法语义

正确使用 HTTP 方法是 RESTful API 的核心。每种方法都有明确的语义、幂等性和安全性要求。

GET
获取资源

幂等且安全,不改变服务端状态。可被缓存。查询参数用于过滤、排序、分页。

GET /api/v1/users?page=1&size=20&sort=created_at
POST
创建资源

非幂等,每次调用可能创建不同资源。返回 201 Created 及新资源 Location 头。

POST /api/v1/users { "name": "Alice", "email": "alice@example.com" }
PUT
完整替换

幂等,客户端提供完整的资源表示。缺失字段视为置空或默认值。返回 200 OK。

PUT /api/v1/users/123 { "name": "Alice", "email": "new@example.com" }
PATCH
部分更新

非幂等,只传递需要修改的字段。支持 JSON Patch (RFC 6902) 或 Merge Patch (RFC 7396)。

PATCH /api/v1/users/123 { "email": "new@example.com" }
DELETE
删除资源

幂等,删除后后续 DELETE 返回 404。可返回 204 No Content 或 200 OK。

DELETE /api/v1/users/123
03

状态码使用

选择合适的 HTTP 状态码能让客户端准确理解请求结果。以下是常用的状态码及其使用场景。

2xx · 成功
200 OK        — GET/PUT/PATCH 成功返回资源
201 Created   — POST 创建成功,返回 Location 头
202 Accepted  — 异步任务已接受,稍后处理
204 No Content — DELETE 成功,无返回体
3xx · 重定向
301 Moved Permanently — 资源永久迁移
302 Found              — 临时重定向
304 Not Modified       — 缓存未过期 (ETag/If-None-Match)
307 Temporary Redirect — 临时重定向,保持 HTTP 方法
4xx · 客户端错误
400 Bad Request   — 请求格式错误
401 Unauthorized   — 未认证,需要登录
403 Forbidden      — 已认证但无权限
404 Not Found      — 资源不存在
405 Method Not Allowed — 方法不允许
409 Conflict       — 资源冲突(如重复创建)
422 Unprocessable Entity — 校验失败
429 Too Many Requests    — 请求限流
5xx · 服务端错误
500 Internal Server Error — 服务端内部错误
502 Bad Gateway           — 网关/代理错误
503 Service Unavailable   — 服务暂时不可用
504 Gateway Timeout       — 网关超时
04

错误处理

统一的错误响应格式让客户端能够一致地处理各种错误情况。建议遵循 RFC 7807 Problem Details 规范。

标准错误格式

// RFC 7807 Problem Details { "type": "https://api.example.com/errors/validation", "title": "Validation Error", "status": 422, "detail": "email 字段格式不正确", "instance": "/api/v1/users", "errors": { "email": "请输入有效的邮箱地址", "age": "年龄必须在 1-150 之间" } }

错误码设计原则

  • 分层设计:服务级 + 模块级 + 具体错误码,如 AUTH_TOKEN_EXPIRED
  • 可读性强:使用大写蛇形命名,一目了然
  • 国际化:错误信息支持多语言,通过 Accept-Language 头切换
  • 日志追踪:返回 trace_id 便于服务端排查
  • 安全考虑:不要泄露敏感信息(堆栈、SQL、路径)
06

认证方式

选择合适的认证方式对 API 安全性至关重要。以下是三种主流认证方案的对比和最佳实践。

JWT (JSON Web Token)

无状态认证,token 包含用户信息和 claims。服务端无需存储 session,适合分布式架构。

// Header Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
  • 支持 Token 刷新机制
  • 设置合理的过期时间(Access: 15min, Refresh: 7d)
  • 重要操作需额外验证(OTP/生物识别)

OAuth 2.0

授权框架,允许第三方应用获取有限的资源访问权限。支持授权码、客户端凭证等多种流程。

// 授权码流程 GET /authorize?response_type=code&client_id=xxx&redirect_uri=yyy
  • 授权码 + PKCE 是移动端最佳实践
  • Client Credentials 用于服务间通信
  • 使用 Scope 控制最小权限

API Key

最简单的认证方式,适用于服务端到服务端、公共 API 或内部工具。通过 Header 或查询参数传递。

// Header X-API-Key: sk-xxxxxxxxxxxxxxxx
  • 配合 IP 白名单增强安全性
  • 定期轮换密钥
  • 支持多 Key 隔离不同权限
07

API 版本控制

API 版本管理是保证向后兼容性的关键策略。不同的版本控制方式在可维护性和易用性上各有优劣。

URL 路径版本(推荐)

GET /api/v1/users GET /api/v2/users

优点:直观、易于调试、支持 CDN 缓存、适合大型公共 API。

缺点:URL 不够简洁、版本升级成本高。

Header / 内容协商

GET /api/users Accept: application/vnd.myapp.v1+json

优点:URL 干净、支持细粒度版本控制、适合媒体类型变化。

缺点:调试不便、工具兼容性差、对新手不友好。

版本管理最佳实践

  • 制定明确的版本弃用策略(如:v2 发布后 v1 保持 12 个月)
  • 在响应头中加入弃用警告:Sunset: Sat, 31 Dec 2025 23:59:59 GMT
  • 使用 Deprecation 头提示客户端即将弃用
  • 提供版本迁移指南和 changelog
  • 大版本升级需评估对现有客户端的影响
08

文档与规范

高质量的 API 文档是开发者体验的核心。使用 OpenAPI/Swagger 规范和自动化工具,让文档与代码同步。

OpenAPI / Swagger 规范

// OpenAPI 3.0 示例 openapi: "3.0.3" info: title: 用户管理 API version: "1.0.0" paths: /users: get: summary: 获取用户列表 parameters: - name: page in: query schema: { type: integer, default: 1 } responses: "200": description: 成功返回用户列表 content: application/json: schema: type: array items: { $ref: "#/components/schemas/User" }
📖 Swagger UI

交互式 API 文档浏览,支持在线调试

🔧 Redoc

美观的静态 API 文档渲染

⚡ SpringDoc

Spring Boot 集成 OpenAPI 自动生成

📝 API Changelog

维护清晰的版本变更日志,标注 breaking changes

09

速率限制

Rate Limiting 是保护 API 不被滥用的重要机制。通过标准化的响应头告知客户端当前的限流状态。

标准限流响应头

// 请求响应头 X-RateLimit-Limit: 100 // 窗口内最大请求数 X-RateLimit-Remaining: 85 // 当前窗口剩余请求 X-RateLimit-Reset: 1625097600 // 窗口重置时间戳 // 超限时返回 429 及 Retry-After 429 Too Many Requests Retry-After: 3600

限流算法对比

算法原理优点缺点
令牌桶以固定速率添加令牌,请求消耗令牌允许突发流量,实现简单允许桶容量范围内突发
漏桶请求进入队列,以固定速率处理流量平滑,输出稳定无法应对突发
固定窗口时间窗口内计数,超限拒绝实现最简单窗口边界突发
滑动窗口基于时间区间的精确计数限流均匀,避免边界问题实现较复杂
10

HATEOAS 与 REST 成熟度模型

Richardson Maturity Model(RMM)定义了 REST API 的四个成熟度等级,帮助团队渐进式地提升 API 质量。

Level 0

The Swamp of POX

使用 HTTP 作为传输隧道,一个 URL 一个方法(通常是 POST),所有操作通过请求体区分。常见于早期 SOAP/XML-RPC。

POST /api { "method": "getUser", "params": { "id": 123 } }
Level 1

Resources

引入资源概念,每个资源有独立 URL。但仍使用单一 HTTP 方法。

POST /api/users/123/getOrders POST /api/users/123/createOrder
Level 2

HTTP Verbs

正确使用 HTTP 方法语义(GET/POST/PUT/DELETE),结合状态码表达结果。这是大多数 API 的目标级别。

GET /api/users/123 POST /api/users PUT /api/users/123 DELETE /api/users/123
Level 3

HATEOAS

响应中包含链接(links),客户端通过链接发现可执行的操作,实现超媒体驱动。

{ "id": 123, "name": "Alice", "_links": { "self": "/api/users/123", "orders": "/api/users/123/orders", "update": { "href": "/api/users/123", "method": "PUT" } } }

HATEOAS 设计要点

  • 使用 _linkslinks 字段包含相关资源链接
  • 每个链接包含 href 和可选的 method/rel 属性
  • 分页响应中包含 first/prev/next/last 链接
  • 链接随资源状态变化(如:订单已支付后不再显示"取消"链接)
  • 实现难度高,推荐在 Level 2 的基础上按需采用

接口从能用到好用,还差这些规范

统一响应

{
  "code": "USER_NOT_FOUND",
  "message": "用户不存在",
  "traceId": "8f12a...",
  "data": null
}

分页过滤

GET /api/orders?cursor=xxx&limit=20&sort=-createdAt&fields=id,status,total

幂等请求

POST /api/payments
Idempotency-Key: order_1001_pay_1

废弃策略

Deprecation: true
Sunset: Wed, 30 Dec 2026 23:59:59 GMT

错误码设计

  • HTTP 状态码表达协议层结果。
  • 业务 code 表达可识别错误。
  • traceId 贯穿日志和链路追踪。

API 安全

  • 鉴权、签名、限流、审计不可缺。
  • 敏感字段默认不返回。
  • 管理端接口必须二次校验权限。

OpenAPI 流程

  • 接口先写 schema。
  • CI 校验文档和实现一致。
  • 变更记录写入 changelog。

把规范写进接口契约

Rate Limit Header

HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
Retry-After: 60

Cursor Pagination

{
  "items": [],
  "nextCursor": "eyJpZCI6MTAwMX0=",
  "hasMore": true
}

OpenAPI 错误响应

components:
  schemas:
    ErrorResponse:
      required: [code, message, traceId]