flowchart LR
P1["客户端-服务器"]
P2["无状态"]
P3["可缓存"]
P4["分层系统"]
P5["统一接口"]
P6["按需代码"]
flowchart LR
Do["✅ 应该"]
Dont["❌ 避免"]
Do --> D1["使用名词 /users"]
Do --> D2["使用复数"]
Do --> D3["嵌套资源"]
Dont --> X1["使用动词 /getUsers"]
Dont --> X2["文件扩展名 .json"]
sequenceDiagram
participant C as 客户端
participant S as REST API
C->>S: POST /users {name:张三}
S->>C: 201 Created {id:456}
C->>S: GET /users/456
S->>C: 200 OK {id:456}
REST(Representational State Transfer,表述性状态转移)是一种软件架构风格,由Roy Fielding在2000年的博士论文中首次提出。RESTful API则是遵循REST原则设计的Web API接口。
RESTful API的核心特征包括:
| 原则 | 说明 | 实现方式 |
|---|---|---|
| 客户端-服务器分离 | 客户端与服务端独立演化,互不依赖 | 前后端分离架构 |
| 无状态 | 每个请求包含所有必要信息,服务端不保存会话状态 | 请求中携带认证信息 |
| 可缓存 | 响应必须定义是否可缓存,减少网络往返 | Cache-Control header |
| 统一接口 | 资源通过统一接口访问,操作语义标准化 | HTTP方法+URL定位资源 |
| 分层系统 | 客户端无法判断是否直连终端服务器 | 通过网关、负载均衡器分层 |
GET /users # 获取用户列表
GET /users/123 # 获取ID为123的用户
POST /users # 创建新用户
PUT /users/123 # 更新用户
DELETE /users/123 # 删除用户
GET /getUsers # 错误:使用动词
POST /createUser # 错误:使用动词
DELETE /deleteUser/123 # 错误:使用动词
# 用户123发表的所有文章
GET /users/123/articles
# 用户123的文章456的评论
GET /users/123/articles/456/comments
# 推荐:嵌套不超过2-3层
GET /users/123/posts
GET /posts/456/comments
嵌套层级不宜超过3层,过深的嵌套会使URL复杂且难以维护。如果层级过深,考虑使用查询参数或直接使用根资源。
| 规范 | 推荐 | 不推荐 |
|---|---|---|
| 复数名词 | /users |
/user |
| 小写字母 | /user-profiles |
/UserProfiles |
| kebab-case | /order-items |
/order_items |
| 清晰简洁 | /articles/123 |
/articles/show/123 |
RESTful API使用HTTP方法表达操作语义:
| 方法 | 用途 | 幂等性 | 安全性 | 请求体 |
|---|---|---|---|---|
GET |
获取资源 | 是 | 是 | 无 |
POST |
创建资源 | 否 | 否 | 有 |
PUT |
全量更新 | 是 | 否 | 有 |
PATCH |
部分更新 | 否 | 否 | 有 |
DELETE |
删除资源 | 是 | 否 | 通常无 |
GET /users/123?fields=name,email HTTP/1.1
Host: api.example.com
Accept: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: max-age=3600
{
"id": 123,
"name": "张三",
"email": "zhangsan@example.com",
"created_at": "2026-01-15T10:30:00Z"
}
POST /users HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
{
"name": "李四",
"email": "lisi@example.com",
"password": "secure_password_123"
}
HTTP/1.1 201 Created
Location: /users/456
Content-Type: application/json
{
"id": 456,
"name": "李四",
"email": "lisi@example.com",
"created_at": "2026-04-10T08:00:00Z"
}
PUT /users/123 HTTP/1.1
Content-Type: application/json
{
"id": 123,
"name": "张三更新版",
"email": "zhangsan_new@example.com",
"role": "admin",
"status": "active"
}
-- 注意:PUT需要包含所有字段,缺失字段会被置为null或默认值 --
PATCH /users/123 HTTP/1.1
Content-Type: application/json
{
"name": "张三更新版"
}
-- 注意:PATCH只需包含要修改的字段,其他字段保持不变 --
合理使用HTTP状态码是RESTful API的重要实践:
| 状态码 | 含义 | 使用场景 |
|---|---|---|
| 2xx 成功 | ||
200 OK |
请求成功 | GET成功、PUT/PATCH更新成功 |
201 Created |
资源创建成功 | POST创建新资源,响应中包含Location头 |
204 No Content |
无返回内容 | DELETE成功,响应无body |
| 3xx 重定向 | ||
304 Not Modified |
资源未修改 | 配合ETag实现缓存 |
| 4xx 客户端错误 | ||
400 Bad Request |
请求格式错误 | 参数校验失败、JSON格式错误 |
401 Unauthorized |
未认证 | 缺少或无效的认证信息 |
403 Forbidden |
无权限 | 认证通过但无访问权限 |
404 Not Found |
资源不存在 | URL对应的资源不存在 |
409 Conflict |
资源冲突 | 重复创建、版本冲突 |
422 Unprocessable Entity |
语义错误 | 请求格式正确但语义错误 |
429 Too Many Requests |
请求过多 | 触发限流 |
| 5xx 服务端错误 | ||
500 Internal Server Error |
服务端错误 | 通用服务端异常 |
502 Bad Gateway |
网关错误 | 上游服务异常 |
503 Service Unavailable |
服务不可用 | 维护或过载 |
查看完整的状态码说明:HTTP状态码速查工具
{
"data": {
"id": 123,
"name": "张三",
"email": "zhangsan@example.com"
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2026-04-10T08:00:00Z"
}
}
{
"data": [...],
"pagination": {
"page": 2,
"per_page": 20,
"total": 100,
"total_pages": 5
},
"links": {
"self": "/users?page=2",
"next": "/users?page=3",
"prev": "/users?page=1"
}
}
| 请求头 | 说明 | 示例 |
|---|---|---|
Accept |
告诉服务器客户端能处理的格式 | application/json |
Content-Type |
请求体的格式 | application/json |
Authorization |
认证信息 | Bearer xxx |
If-None-Match |
条件请求,用于缓存 | "123456" |
Idempotency-Key |
幂等性键,防止重复提交 | uuid-xxx |
统一的错误响应格式对客户端调试至关重要:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "请求参数校验失败",
"details": [
{
"field": "email",
"message": "邮箱格式不正确"
},
{
"field": "password",
"message": "密码长度至少8位"
}
],
"request_id": "req_abc123"
}
}
// 使用大写下划线格式
VALIDATION_ERROR // 校验错误
RESOURCE_NOT_FOUND // 资源不存在
UNAUTHORIZED // 未认证
FORBIDDEN // 无权限
RATE_LIMITED // 限流
INTERNAL_ERROR // 服务端错误
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"code": "VALIDATION_ERROR",
"message": "创建用户失败",
"details": [
{"field": "email", "message": "邮箱已被注册"},
{"field": "username", "message": "用户名不能为空"}
],
"request_id": "req_xyz789"
}
}
API版本管理确保前端与后端可以独立演进。常见的版本管理策略:
| 策略 | 示例 | 优点 | 缺点 |
|---|---|---|---|
| URL路径 | /api/v1/users |
直观、强制版本感知 | URL变更 |
| Header | API-Version: v1 |
URL不变 | 不够直观 |
| 查询参数 | /api/users?version=1 |
简单 | 可能被缓存 |
# v1版本
GET /api/v1/users/123
# v2版本 - 可能返回不同结构
GET /api/v2/users/123
# v2响应可能包含v1没有的字段
{
"id": 123,
"name": "张三",
"email": "zhangsan@example.com",
"avatar_url": "https://...",
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-04-10T08:00:00Z"
}
| 方式 | 适用场景 | 安全性 |
|---|---|---|
| API Key | 服务端间调用 | 中等 |
| Basic Auth | 简单场景,不推荐 | 低 |
| Bearer Token (JWT) | Web/Mobile应用 | 高 |
| OAuth 2.0 | 第三方授权 | 高 |
# 请求头携带Token
GET /api/v1/users/123 HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
# Token Payload示例
{
"sub": "user_123",
"name": "张三",
"role": "admin",
"exp": 1712720000
}
如果API有跨域需求,正确配置CORS头:
Access-Control-Allow-Origin: https://your-frontend.com
Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
Access-Control-Max-Age: 86400