一、RESTful 基础概念
1.1 什么是 RESTful?
RESTful 的全称是 Representational State Transfer(表现层状态转换)。
code
RESTful 词义分解:
├── Representational(表现层)
│ └── 客户端所需的资源(JSON 数据、图片数据等)
├── State(状态)
│ └── 资源的当前状态
└── Transfer(转换)
└── 对资源进行操作,改变资源状态1.2 核心概念解析
表现层(Representational)
code
表现层 = 资源的表现形式
资源类型:
├── 数据资源
│ ├── JSON 格式数据
│ ├── XML 格式数据
│ └── 其他结构化数据
├── 文件资源
│ ├── 图片文件
│ ├── 视频文件
│ └── 文档文件
└── 服务资源
├── 计算服务
└── 数据处理服务状态转换(State Transfer)
code
状态转换 = 对资源的操作
用户操作 → HTTP 方法 → 服务器资源变化:
├── 获取资源 → GET → 读取资源状态
├── 创建资源 → POST → 新增资源
├── 更新资源 → PUT → 完整更新资源
├── 部分更新 → PATCH → 部分更新资源
└── 删除资源 → DELETE → 删除资源1.3 RESTful 接口定义
RESTful 接口是一种以资源为中心的设计风格,使用 HTTP 协议实现对资源的 CRUD 操作。
code
RESTful 接口特点:
├── 以资源为中心
│ └── URL 表示资源,HTTP 方法表示操作
├── 统一接口
│ └── 使用标准 HTTP 方法(GET、POST、PUT、DELETE)
├── 无状态
│ └── 每个请求包含所有必要信息
└── 易于理解和使用
└── 语义化强,结构清晰1.4 REST 风格 vs RESTful 接口
code
概念区别:
├── RESTful 接口
│ ├── 定义:一种接口设计风格
│ └── 范围:单个接口的设计规范
└── REST 风格
├── 定义:一种软件架构风格
└── 范围:整个系统的所有资源操作都遵循 RESTful 接口规范理解:如果说一个项目是"遵循 REST 风格设计"的,意味着系统里面所有资源的操作都遵循 RESTful 接口规范。
二、RESTful 接口设计规范
2.1 接口定义的四大组成部分
code
RESTful 接口定义结构:
┌─────────────────────────────────────┐
│ 1. 资源命名与 URL 设计 │
│ ├── 接口用途说明 │
│ └── 请求 URL 地址 │
├─────────────────────────────────────┤
│ 2. HTTP 方法与操作 │
│ ├── GET(获取资源) │
│ ├── POST(创建资源) │
│ ├── PUT(更新资源) │
│ ├── PATCH(部分更新) │
│ └── DELETE(删除资源) │
├─────────────────────────────────────┤
│ 3. 详细内容 │
│ ├── 请求参数 │
│ │ ├── 路径参数(Path) │
│ │ ├── 查询参数(Query) │
│ │ └── 请求体(Body) │
│ └── 响应数据 │
│ ├── 响应状态码 │
│ ├── 响应数据 │
│ └── 响应消息 │
├─────────────────────────────────────┤
│ 4. 错误处理 │
│ ├── 错误状态码 │
│ └── 错误消息 │
└─────────────────────────────────────┘2.2 资源命名与 URL 设计
URL 设计原则
code
URL 设计原则:
├── 使用名词表示资源
│ ├── 正确:/users、/articles
│ └── 错误:/getUsers、/createArticle
├── 使用复数形式
│ ├── 正确:/users、/products
│ └── 错误:/user、/product
├── 层级结构清晰
│ ├── /users/{id}/orders(用户的订单)
│ └── /articles/{id}/comments(文章的评论)
├── 使用小写字母和连字符
│ ├── 正确:/user-profiles、/order-items
│ └── 错误:/userProfiles、/OrderItems
└── 版本控制
└── /api/v1/users、/api/v2/productsURL 命名规范对比
| 命名方式 | 示例 | 推荐程度 | 说明 |
|---|---|---|---|
| 短横线 | /user-profiles | 最推荐,语义清晰 | |
| 下划线 | /user_profiles | 可用,但不推荐 | |
| 小驼峰 | /userProfiles | 不推荐 | |
| 大驼峰 | /UserProfiles | 不推荐 |
2.3 HTTP 方法与 CRUD 操作
code
HTTP 方法与资源操作映射:
┌──────────┬──────────┬──────────────┬──────────────────┐
│ HTTP方法 │ 操作 │ CRUD映射 │ 示例 │
├──────────┼──────────┼──────────────┼──────────────────┤
│ GET │ 获取资源 │ Read(读取) │ GET /users │
│ POST │ 创建资源 │ Create(创建)│ POST /users │
│ PUT │ 完整更新 │ Update(更新)│ PUT /users/1 │
│ PATCH │ 部分更新 │ Update(更新)│ PATCH /users/1 │
│ DELETE │ 删除资源 │ Delete(删除)│ DELETE /users/1 │
└──────────┴──────────┴──────────────┴──────────────────┘各方法详细说明
GET - 获取资源
http
# RESTful 接口设计规范
GET /api/v1/users
# 获取单个用户
GET /api/v1/users/123
# 查询参数过滤
GET /api/v1/users?name=zhang&age=25POST - 创建资源
http
# 创建新用户
POST /api/v1/users
Content-Type: application/json
{
"name": "张三",
"email": "zhangsan@example.com",
"age": 25
}PUT - 完整更新资源
http
# 完整更新用户信息(需要提供所有字段)
PUT /api/v1/users/123
Content-Type: application/json
{
"name": "李四",
"email": "lisi@example.com",
"age": 28
}PATCH - 部分更新资源
http
# 部分更新用户信息(只更新提供的字段)
PATCH /api/v1/users/123
Content-Type: application/json
{
"age": 26
}DELETE - 删除资源
http
# 删除用户
DELETE /api/v1/users/1232.4 请求参数设计
code
请求参数类型:
├── 路径参数(Path Parameters)
│ ├── 用途:标识特定资源
│ ├── 示例:/users/{id}
│ └── 特点:必需,不可省略
├── 查询参数(Query Parameters)
│ ├── 用途:过滤、排序、分页
│ ├── 示例:/users?name=zhang&page=1&size=10
│ └── 特点:可选,可组合
└── 请求体参数(Body Parameters)
├── 用途:创建或更新资源的数据
├── 示例:JSON 格式的数据对象
└── 特点:用于 POST、PUT、PATCH查询参数示例
code
常见查询参数:
├── 过滤(Filter)
│ └── /users?status=active&role=admin
├── 排序(Sort)
│ └── /users?sort=created_at&order=desc
├── 分页(Pagination)
│ └── /users?page=1&size=20
└── 字段选择(Field Selection)
└── /users?fields=id,name,email2.5 响应数据格式
标准响应结构
json
{
"code": 200, // 响应状态码
"message": "请求成功", // 响应消息
"data": {
// 响应数据
"id": 123,
"name": "张三",
"email": "zhangsan@example.com"
}
}列表数据响应格式
json
{
"code": 200,
"message": "获取成功",
"data": {
"list": [
{ "id": 1, "name": "张三" },
{ "id": 2, "name": "李四" }
],
"pagination": {
"page": 1,
"size": 20,
"total": 100,
"totalPages": 5
}
}
}错误响应格式
json
{
"code": 400,
"message": "请求参数错误",
"error": {
"field": "email",
"detail": "邮箱格式不正确"
}
}三、HTTP 状态码详解
3.1 状态码分类
code
HTTP 状态码分类:
├── 1xx:信息性状态码
│ └── 接收的请求正在处理
├── 2xx:成功状态码
│ └── 请求正常处理完毕
├── 3xx:重定向状态码
│ └── 需要进行附加操作以完成请求
├── 4xx:客户端错误状态码
│ └── 服务器无法处理请求
└── 5xx:服务器错误状态码
└── 服务器处理请求出错3.2 常用状态码详解
2xx - 成功状态码
| 状态码 | 名称 | 说明 | 使用场景 |
|---|---|---|---|
| 200 | OK | 请求成功 | GET、PATCH 请求成功 |
| 201 | Created | 创建成功 | POST 请求创建资源成功 |
| 204 | No Content | 请求成功,无响应内容 | DELETE 请求成功 |
| 202 | Accepted | 请求已接受,处理中 | 异步任务 |
| 206 | Partial Content | 部分内容 | 分段下载 |
使用示例:
code
200 OK - GET 请求成功
├── GET /users/123
└── 响应:返回用户详细信息
201 Created - POST 创建成功
├── POST /users
└── 响应:返回新创建的用户信息 + Location 头
204 No Content - DELETE 删除成功
├── DELETE /users/123
└── 响应:无响应体,只有状态码3xx - 重定向状态码
| 状态码 | 名称 | 说明 | 使用场景 |
|---|---|---|---|
| 301 | Moved Permanently | 永久重定向 | 资源永久移动 |
| 302 | Found | 临时重定向 | 资源临时移动 |
| 304 | Not Modified | 资源未修改,使用缓存 | 缓存验证 |
| 307 | Temporary Redirect | 临时重定向(保持方法) | POST 重定向 |
4xx - 客户端错误状态码
| 状态码 | 名称 | 说明 | 使用场景 |
|---|---|---|---|
| 400 | Bad Request | 请求参数错误 | 参数格式不正确 |
| 401 | Unauthorized | 未认证,需要登录 | 缺少认证信息 |
| 403 | Forbidden | 已认证,但无权限 | 权限不足 |
| 404 | Not Found | 资源不存在 | URL 错误或资源已删除 |
| 405 | Method Not Allowed | 方法不允许 | 使用错误的 HTTP 方法 |
| 408 | Request Timeout | 请求超时 | 请求处理超时 |
| 409 | Conflict | 资源冲突 | 重复创建 |
| 422 | Unprocessable Entity | 语义错误 | 验证失败 |
| 429 | Too Many Requests | 请求过多 | 限流 |
常见错误场景:
code
400 Bad Request
├── 场景:请求参数格式错误
└── 示例:{"email": "invalid-email"}
401 Unauthorized
├── 场景:未提供认证信息
└── 示例:缺少 Token 或 Token 过期
403 Forbidden
├── 场景:已登录但无权限访问
└── 示例:普通用户访问管理员接口
404 Not Found
├── 场景:资源不存在
└── 示例:GET /users/999(用户ID不存在)5xx - 服务器错误状态码
| 状态码 | 名称 | 说明 | 使用场景 |
|---|---|---|---|
| 500 | Internal Server Error | 服务器内部错误 | 代码异常 |
| 502 | Bad Gateway | 网关错误 | 上游服务不可用 |
| 503 | Service Unavailable | 服务不可用 | 服务维护或过载 |
| 504 | Gateway Timeout | 网关超时 | 上游服务超时 |
3.3 状态码最佳实践
code
状态码设计原则:
├── 1. 与 HTTP 状态码保持一致
│ └── 避免自定义状态码与 HTTP 状态码冲突
├── 2. 语义准确
│ ├── 创建成功返回 201,而非 200
│ └── 删除成功返回 204,而非 200
├── 3. 区分客户端错误和服务端错误
│ ├── 4xx:客户端问题,不需要重试
│ └── 5xx:服务端问题,可以重试
└── 4. 提供详细的错误信息
└── 返回错误原因和建议解决方案思考题:课程中提到"1xx 通常是指什么?",留给大家思考。
答案:1xx 是信息性状态码,表示接收的请求正在处理。例如:
- 100 Continue:继续发送请求体
- 101 Switching Protocols:协议切换(如 WebSocket 握手)
- 102 Processing:服务器已收到请求,正在处理
四、RESTful 接口设计最佳实践
4.1 文档编写原则
code
接口文档编写五大原则:
┌─────────────────────────────────────┐
│ 1. 简洁明了,易于理解 │
│ ├── 受众:开发人员 │
│ ├── 无需解释常见名词 │
│ └── 使用技术术语 │
├─────────────────────────────────────┤
│ 2. 遵循一致的命名与设计规范 │
│ ├── URL 命名统一 │
│ ├── 参数命名统一 │
│ └── 版本控制统一 │
├─────────────────────────────────────┤
│ 3. 使用合适的 HTTP 方法和状态码 │
│ ├── GET 用于获取 │
│ ├── POST 用于创建 │
│ ├── PUT 用于更新 │
│ ├── DELETE 用于删除 │
│ └── 状态码语义准确 │
├─────────────────────────────────────┤
│ 4. 提供详细的错误信息 │
│ ├── 错误原因 │
│ ├── 错误字段 │
│ └── 解决建议 │
├─────────────────────────────────────┤
│ 5. 注意安全性 │
│ ├── 信道安全(HTTPS) │
│ ├── 身份认证(Authentication) │
│ └── 权限控制(Authorization) │
└─────────────────────────────────────┘4.2 版本控制策略
code
API 版本控制方案:
├── URL 路径方式(推荐)
│ ├── /api/v1/users
│ ├── /api/v2/users
│ └── 优点:简单直观,易于理解
├── 请求头方式
│ ├── Accept: application/vnd.api+json;version=1
│ └── 优点:URL 简洁
└── 查询参数方式
├── /api/users?version=1
└── 优点:灵活,但不够 RESTful版本控制最佳实践:
code
版本控制策略:
├── 主版本号变化(v1 → v2)
│ └── 破坏性更新,不兼容旧版本
├── 版本兼容
│ ├── 旧版本 API 保持运行
│ ├── 提供迁移指南
│ └── 设置弃用时间表
└── 文档说明
├── 每个版本的变更日志
└── 版本升级注意事项4.3 安全性设计
code
接口安全性三大维度:
┌─────────────────────────────────────┐
│ 1. 信道安全 │
│ └── 使用 HTTPS 加密传输 │
├─────────────────────────────────────┤
│ 2. 身份认证(Authentication) │
│ ├── JWT Token │
│ ├── OAuth 2.0 │
│ ├── API Key │
│ └── Session Cookie │
├─────────────────────────────────────┤
│ 3. 权限控制(Authorization) │
│ ├── RBAC(基于角色) │
│ ├── ABAC(基于属性) │
│ └── 资源级权限控制 │
└─────────────────────────────────────┘安全实践示例:
code
接口安全检查清单:
├── 传输安全
│ ├── 强制使用 HTTPS
│ ├── 禁用不安全的 TLS 版本
│ └── 设置 HSTS 头
├── 认证安全
│ ├── Token 有效期控制
│ ├── Token 刷新机制
│ └── 敏感操作二次验证
├── 输入验证
│ ├── 参数类型验证
│ ├── 参数范围验证
│ └── SQL 注入防护
└── 限流控制
├── IP 限流
├── 用户限流
└── 接口限流4.4 接口命名规范示例
用户资源接口设计
code
用户资源 RESTful API 设计:
├── 获取用户列表
│ └── GET /api/v1/users
├── 获取单个用户
│ └── GET /api/v1/users/{id}
├── 创建用户
│ └── POST /api/v1/users
├── 更新用户(完整)
│ └── PUT /api/v1/users/{id}
├── 更新用户(部分)
│ └── PATCH /api/v1/users/{id}
├── 删除用户
│ └── DELETE /api/v1/users/{id}
└── 用户相关资源
├── 获取用户订单
│ └── GET /api/v1/users/{id}/orders
└── 获取用户文章
└── GET /api/v1/users/{id}/articles五、RESTful 接口实战案例
5.1 博客系统 API 设计
code
博客系统 RESTful API 完整设计:
┌──────────────────────────────────────────────────┐
│ 文章资源(Articles) │
├──────────────────────────────────────────────────┤
│ GET /api/v1/articles 获取文章列表 │
│ GET /api/v1/articles/{id} 获取文章详情 │
│ POST /api/v1/articles 创建文章 │
│ PUT /api/v1/articles/{id} 更新文章 │
│ DELETE /api/v1/articles/{id} 删除文章 │
│ │
│ 评论资源(Comments) │
├──────────────────────────────────────────────────┤
│ GET /api/v1/articles/{id}/comments │
│ 获取文章评论列表 │
│ POST /api/v1/articles/{id}/comments │
│ 创建评论 │
│ DELETE /api/v1/comments/{id} 删除评论 │
│ │
│ 用户资源(Users) │
├──────────────────────────────────────────────────┤
│ POST /api/v1/auth/register 用户注册 │
│ POST /api/v1/auth/login 用户登录 │
│ GET /api/v1/users/profile 获取个人信息 │
│ PUT /api/v1/users/profile 更新个人信息 │
└──────────────────────────────────────────────────┘5.2 请求与响应示例
创建文章接口
请求:
http
POST /api/v1/articles
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json
{
"title": "RESTful API 设计最佳实践",
"content": "本文介绍 RESTful API 的设计原则...",
"tags": ["API", "RESTful", "后端"],
"status": "published"
}成功响应(201 Created):
json
{
"code": 201,
"message": "文章创建成功",
"data": {
"id": 123,
"title": "RESTful API 设计最佳实践",
"content": "本文介绍 RESTful API 的设计原则...",
"tags": ["API", "RESTful", "后端"],
"status": "published",
"author": {
"id": 1,
"name": "张三"
},
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:30:00Z"
}
}错误响应(400 Bad Request):
json
{
"code": 400,
"message": "请求参数错误",
"error": {
"errors": [
{
"field": "title",
"message": "标题不能为空"
},
{
"field": "tags",
"message": "标签数量不能超过 5 个"
}
]
}
}六、常见问题与解决方案
| 问题场景 | 问题描述 | 解决方案 |
|---|---|---|
| URL 命名不统一 | 团队成员使用不同的命名风格 | 制定统一的 API 设计规范文档 |
| 状态码使用不当 | 所有响应都返回 200 | 根据实际情况使用正确的 HTTP 状态码 |
| 错误信息不够详细 | 只返回"请求失败" | 提供错误原因、字段和建议解决方案 |
| 缺少版本控制 | 接口更新导致旧客户端失效 | 使用 URL 版本控制,保持向后兼容 |
| 接口文档更新不及时 | 代码修改后文档未同步 | 使用 Swagger 等工具自动生成文档 |
| 安全性不足 | 敏感接口未做权限控制 | 实施身份认证和权限验证 |
| 参数验证不完善 | 后端未验证前端参数 | 添加参数类型、范围、格式验证 |
| 缺少限流机制 | 接口被恶意调用 | 实施限流策略(IP、用户、接口级别) |
七、学习要点总结
必须掌握
-
RESTful 核心概念:Representational State Transfer(表现层状态转换),以资源为中心的设计风格
-
HTTP 方法与 CRUD 映射:
- GET → Read(读取)
- POST → Create(创建)
- PUT/PATCH → Update(更新)
- DELETE → Delete(删除)
-
URL 设计原则:使用名词、复数形式、小写字母、连字符、层级清晰、版本控制
-
HTTP 状态码分类:
- 2xx:成功(200、201、204)
- 4xx:客户端错误(400、401、403、404)
- 5xx:服务器错误(500、502、503)
-
接口设计最佳实践:简洁明了、命名一致、状态码准确、错误详细、注重安全
实践建议
接口设计:
- 使用 RESTful 设计风格,以资源为中心
- URL 使用名词,HTTP 方法表示操作
- 状态码语义化,错误信息详细化
文档编写:
- 使用 Swagger/YApi 等工具自动生成文档
- 提供完整的请求示例和响应示例
- 及时更新文档,保持与代码同步
安全防护:
- 强制使用 HTTPS
- 实施身份认证和权限控制
- 添加参数验证和限流机制
八、延伸学习资源
推荐阅读
- 《RESTful Web APIs》- Leonard Richardson
- 《API 设计模式》- JJ Geewax
- 《HTTP 权威指南》- David Gourley
实用工具
接口文档工具:
- Swagger / OpenAPI
- YApi
- Postman
- Apifox
接口测试工具:
- Postman
- Insomnia
- curl
- HTTPie
接口 Mock 工具:
- Mock.js
- Json-Server
- MirageJS
规范参考
- RESTful API 设计指南:https://restfulapi.net/
- HTTP 状态码列表:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status
- OpenAPI 规范:https://swagger.io/specification/
学习完成!
下一步建议:
- 使用 Swagger 为自己的项目设计 RESTful API
- 按照规范编写一个完整的接口文档
- 实践接口的安全性和错误处理机制
返回导航:见课程笔记分类侧边栏