03 RESTful API 设计规范 - 设计优雅的接口
🎯本章目标:理解RESTful架构风格,掌握URL设计规范、HTTP方法语义,学会阅读和测试RESTful接口。
3.1 什么是RESTful
生活中的类比
想象一个图书馆管理系统:
传统方式(非RESTful): /getUserInfo?id=1 → 获取用户信息 /createUser → 创建用户 /updateUser → 更新用户 /deleteUser?id=1 → 删除用户 RESTful方式: GET /users/1 → 获取用户信息 POST /users → 创建用户 PUT /users/1 → 更新用户 DELETE /users/1 → 删除用户
RESTful的核心思想:用URL定位资源,用HTTP方法描述对资源的操作。
REST的定义
REST(Representational State Transfer,表现层状态转换)是一种软件架构风格,由Roy Fielding在2000年提出。
- 资源 Resources:URL表示
- 表现层 Representation:JSON/XML
- 状态转换 State Transfer:HTTP方法
- 无状态 Stateless:每次请求独立
3.2 RESTful设计六大原则
原则1:URL表示资源,不是动作
| 错误(动词在URL中) | 正确(名词表示资源) |
|---|---|
GET /getUser?id=1 | GET /users/1 |
POST /createUser | POST /users |
POST /updateUser | PUT /users/1 |
GET /deleteUser?id=1 | DELETE /users/1 |
原则2:用HTTP方法表示操作
| HTTP方法 | 操作 | 幂等性 | 示例 |
|---|---|---|---|
| GET | 读取资源 | 是 | GET /users获取用户列表 |
| POST | 创建资源 | 否 | POST /users创建新用户 |
| PUT | 全量更新 | 是 | PUT /users/1替换用户1的全部信息 |
| PATCH | 部分更新 | 否 | PATCH /users/1只更新用户1的邮箱 |
| DELETE | 删除资源 | 是 | DELETE /users/1删除用户1 |
原则3:使用复数名词
/users ✓ 正确 /user ✗ 错误(用复数) /Users ✗ 错误(小写) /getUsers ✗ 错误(不要有动词)
原则4:正确的HTTP状态码
- 成功 → 返回 2xx(200 OK, 201 Created, 204 No Content)
- 客户端错误 → 返回 4xx(400, 401, 403, 404, 422)
- 服务端错误 → 返回 5xx(500, 502, 503)
原则5:使用查询参数过滤、排序、分页
GET /users?role=admin&sort=name&page=1&size=20 ↑ ↑ ↑ ↑ 过滤条件 排序字段 页码 每页数量
原则6:版本控制
/api/v1/users → API版本1 /api/v2/users → API版本2 或放在Header中: Accept: application/vnd.api.v1+json
3.3 RESTful URL设计实战
电商系统接口设计
| 功能 | HTTP方法 | URL | 说明 |
|---|---|---|---|
| 用户模块 | |||
| 获取用户列表 | GET | /api/v1/users | 支持分页、筛选 |
| 获取单个用户 | GET | /api/v1/users/1 | 用户ID为1 |
| 创建用户 | POST | /api/v1/users | Body传用户数据 |
| 更新用户 | PUT | /api/v1/users/1 | 全量更新 |
| 部分更新 | PATCH | /api/v1/users/1 | 部分字段更新 |
| 删除用户 | DELETE | /api/v1/users/1 | 软删除或硬删除 |
| 获取用户订单 | GET | /api/v1/users/1/orders | 嵌套资源 |
| 商品模块 | |||
| 获取商品列表 | GET | /api/v1/products | 支持分类筛选 |
| 获取商品详情 | GET | /api/v1/products/100 | 商品ID为100 |
| 搜索商品 | GET | /api/v1/products?keyword=手机 | 关键词搜索 |
| 订单模块 | |||
| 创建订单 | POST | /api/v1/orders | 从购物车创建 |
| 获取订单 | GET | /api/v1/orders/2024001 | 订单号 |
| 取消订单 | PUT | /api/v1/orders/2024001/status | 更新状态 |
| 获取订单商品 | GET | /api/v1/orders/2024001/items | 订单明细 |
3.4 请求和响应的数据格式
标准响应结构
{ "code": 0, "message": "success", "data": { "id": 1, "name": "张三", "email": "zhangsan@example.com" } }分页响应结构
{ "code": 0, "message": "success", "data": { "list": [ {"id": 1, "name": "张三"}, {"id": 2, "name": "李四"} ], "pagination": { "page": 1, "size": 20, "total": 100, "totalPages": 5 } } }错误响应结构
{ "code": 1001, "message": "用户名或密码错误", "data": null, "details": { "field": "password", "reason": "密码长度不足" } }3.5 RESTful API测试要点
测试维度
- URL规范:是否使用复数名词、是否无动词、嵌套资源是否合理
- HTTP方法:GET只读、POST创建、PUT/PATCH更新、DELETE删除
- 状态码:2xx成功、4xx客户端错误、5xx服务端错误
- 响应格式:统一结构、错误信息清晰、分页信息完整
测试检查清单
| 检查项 | 说明 | 通过标准 |
|---|---|---|
| URL设计 | 是否使用名词复数 | /users✓/getUsers✗ |
| HTTP方法 | 方法是否语义正确 | GET获取、POST创建、PUT更新、DELETE删除 |
| 状态码 | 返回码是否合理 | 创建返回201、删除返回204 |
| 响应格式 | 结构是否统一 | 包含code、message、data |
| 错误处理 | 错误信息是否友好 | 包含错误码和详细说明 |
| 分页 | 分页参数是否支持 | page、size、total |
| 过滤排序 | 查询参数是否支持 | ?role=admin&sort=name |
| 版本控制 | API是否有版本 | /api/v1/... |
3.6 实战:分析一个RESTful接口文档
接口文档示例
# 用户管理接口 ## 获取用户列表 GET /api/v1/users 请求参数: page: 页码 (默认1) size: 每页数量 (默认20) role: 角色筛选 (可选) 响应: 200 OK { "code": 0, "data": { "list": [...], "pagination": {...} } } ## 获取单个用户 GET /api/v1/users/{id} 路径参数: id: 用户ID 响应: 200 OK - 用户存在 404 Not Found - 用户不存在 ## 创建用户 POST /api/v1/users 请求体: { "name": "张三", "email": "zhangsan@example.com", "role": "user" } 响应: 201 Created { "code": 0, "data": {"id": 1, "name": "张三", ...} } 400 Bad Request - 参数错误 409 Conflict - 邮箱已存在 ## 更新用户 PUT /api/v1/users/{id} 请求体: { "name": "张三", "email": "zhangsan@example.com", "role": "admin" } 响应: 200 OK 404 Not Found ## 删除用户 DELETE /api/v1/users/{id} 响应: 204 No Content 404 Not Found测试用例设计
- GET /users:正常分页、带筛选条件、边界值(page=0)
- GET /users/1:存在的用户、不存在的用户、非法ID(abc)
- POST /users:正常创建、缺少必填字段、邮箱格式错误、重复邮箱
- PUT /users/1:正常更新、更新不存在的用户、非法字段值
- DELETE /users/1:正常删除、删除不存在的用户、无权限删除
3.7 非RESTful接口怎么办
现实情况
不是所有接口都是纯RESTful的,常见变体:
- 纯RESTful:严格遵循6原则
- 类RESTful:大部分RESTful,少量自定义
- RPC风格HTTP:全用POST,URL含动作
- GraphQL:单一端点,查询语言
类RESTful示例
POST /api/v1/users/1/enable → 启用用户(自定义动作) POST /api/v1/users/1/disable → 禁用用户(自定义动作) POST /api/v1/orders/1/refund → 订单退款(自定义动作)
测试策略:理解设计意图,按实际规范测试,不必强求纯RESTful。
3.8 本章小结
RESTful核心要点
- URL设计:名词复数、无动词、嵌套资源
- HTTP方法:GET读 POST建 PUT PATCH更新 DELETE删
- 状态码:201创建 204删除 404不存在
- 响应格式:统一结构、错误清晰、分页完整
课后练习 📝
- 设计题:为一个博客系统设计RESTful API,包含文章、评论、标签、用户四个模块。
- 分析题:分析你工作中或常用的API,判断是否符合RESTful规范,有哪些可以改进的地方。
- 测试题:针对上面的用户管理接口文档,写出至少10个测试用例(包含正常和异常场景)。
3.9 下章预告
下一章我们将学习常见接口类型和数据格式(JSON、XML、GraphQL等),以及如何在接口测试中使用它们!
"RESTful不是教条,而是一种优雅的设计哲学。理解它,你就能设计出让人愉悦的API。"