RESTful API 最佳实践 #
概述 #
本章总结 RESTful API 设计的最佳实践,帮助开发者设计出高质量、易用、可维护的 API。
text
┌─────────────────────────────────────────────────────────────┐
│ 优秀 API 的特征 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ✅ 易于理解和使用 │
│ - 直观的 URL 设计 │
│ - 清晰的命名 │
│ - 一致的风格 │
│ │
│ ✅ 功能完整 │
│ - 支持完整的 CRUD 操作 │
│ - 支持过滤、排序、分页 │
│ - 良好的错误处理 │
│ │
│ ✅ 安全可靠 │
│ - 完善的认证授权 │
│ - 数据验证 │
│ - 速率限制 │
│ │
│ ✅ 性能优良 │
│ - 合理的缓存策略 │
│ - 压缩传输 │
│ - 按需返回数据 │
│ │
│ ✅ 文档完善 │
│ - 清晰的 API 文档 │
│ - 使用示例 │
│ - 错误码说明 │
│ │
└─────────────────────────────────────────────────────────────┘
URL 设计最佳实践 #
text
┌─────────────────────────────────────────────────────────────┐
│ URL 设计最佳实践 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ✅ 使用名词表示资源 │
│ GET /users 获取用户列表 │
│ GET /users/123 获取指定用户 │
│ │
│ ✅ 使用复数形式 │
│ GET /users ✅ │
│ GET /user ❌ │
│ │
│ ✅ 使用小写字母和连字符 │
│ GET /order-items ✅ │
│ GET /OrderItems ❌ │
│ GET /order_items ❌ │
│ │
│ ✅ 表达资源层级关系 │
│ GET /users/123/orders 用户的订单 │
│ GET /orders/456/items 订单的订单项 │
│ │
│ ✅ 使用查询参数过滤 │
│ GET /users?status=active 过滤活跃用户 │
│ GET /products?category=phone 过滤手机类商品 │
│ │
│ ❌ 避免在 URL 中使用动词 │
│ GET /getUsers ❌ │
│ POST /createUser ❌ │
│ │
│ ❌ 避免文件扩展名 │
│ GET /users.json ❌ │
│ │
│ ❌ 避免尾部斜杠 │
│ GET /users/ ❌ │
│ │
└─────────────────────────────────────────────────────────────┘
HTTP 方法最佳实践 #
text
┌─────────────────────────────────────────────────────────────┐
│ HTTP 方法最佳实践 │
├─────────────────────────────────────────────────────────────┤
│ │
│ GET - 获取资源 │
│ ───────────────────────────────────────────── │
│ GET /users 获取用户列表 │
│ GET /users/123 获取单个用户 │
│ GET /users/123/orders 获取用户订单 │
│ │
│ ✅ 安全、幂等、可缓存 │
│ ✅ 参数通过 URL 传递 │
│ ✅ 不修改资源状态 │
│ │
│ POST - 创建资源 │
│ ───────────────────────────────────────────── │
│ POST /users 创建用户 │
│ POST /users/123/orders 创建订单 │
│ │
│ ✅ 返回 201 Created │
│ ✅ 返回 Location 头 │
│ ✅ 数据通过请求体传递 │
│ │
│ PUT - 完整更新 │
│ ───────────────────────────────────────────── │
│ PUT /users/123 完整更新用户 │
│ │
│ ✅ 幂等 │
│ ✅ 提供完整资源数据 │
│ ✅ 未提供字段会被清空 │
│ │
│ PATCH - 部分更新 │
│ ───────────────────────────────────────────── │
│ PATCH /users/123 部分更新用户 │
│ │
│ ✅ 只提供需要更新的字段 │
│ ✅ 未提供字段保持不变 │
│ │
│ DELETE - 删除资源 │
│ ───────────────────────────────────────────── │
│ DELETE /users/123 删除用户 │
│ │
│ ✅ 幂等 │
│ ✅ 返回 204 No Content 或 200 OK │
│ │
└─────────────────────────────────────────────────────────────┘
状态码最佳实践 #
text
┌─────────────────────────────────────────────────────────────┐
│ 状态码最佳实践 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 成功响应 │
│ ───────────────────────────────────────────── │
│ 200 OK 请求成功 │
│ 201 Created 资源创建成功 │
│ 204 No Content 成功但无返回内容 │
│ │
│ 客户端错误 │
│ ───────────────────────────────────────────── │
│ 400 Bad Request 请求格式错误 │
│ 401 Unauthorized 未认证 │
│ 403 Forbidden 无权限 │
│ 404 Not Found 资源不存在 │
│ 409 Conflict 资源冲突 │
│ 422 Unprocessable 验证失败 │
│ 429 Too Many 速率限制 │
│ │
│ 服务端错误 │
│ ───────────────────────────────────────────── │
│ 500 Internal 服务器内部错误 │
│ 503 Unavailable 服务不可用 │
│ │
│ 最佳实践: │
│ ✅ 使用正确的状态码 │
│ ✅ 状态码与错误类型匹配 │
│ ✅ 不要所有错误都返回 500 │
│ │
└─────────────────────────────────────────────────────────────┘
响应格式最佳实践 #
text
┌─────────────────────────────────────────────────────────────┐
│ 响应格式最佳实践 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 单个资源响应: │
│ { │
│ "id": 123, │
│ "name": "张三", │
│ "email": "zhangsan@example.com", │
│ "createdAt": "2025-01-15T10:30:00Z", │
│ "updatedAt": "2025-03-20T15:45:00Z" │
│ } │
│ │
│ 资源列表响应: │
│ { │
│ "data": [...], │
│ "pagination": { │
│ "page": 1, │
│ "limit": 20, │
│ "total": 100 │
│ } │
│ } │
│ │
│ 错误响应: │
│ { │
│ "error": { │
│ "code": "VALIDATION_ERROR", │
│ "message": "Validation failed", │
│ "details": [...], │
│ "requestId": "req-xxx" │
│ } │
│ } │
│ │
│ 最佳实践: │
│ ✅ 使用 JSON 格式 │
│ ✅ 属性使用 camelCase │
│ ✅ 时间使用 ISO 8601 格式 │
│ ✅ 列表响应包含分页信息 │
│ ✅ 错误响应包含错误码和详细信息 │
│ │
└─────────────────────────────────────────────────────────────┘
安全最佳实践 #
text
┌─────────────────────────────────────────────────────────────┐
│ 安全最佳实践 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 认证授权 │
│ ───────────────────────────────────────────── │
│ ✅ 使用 HTTPS │
│ ✅ 使用 JWT 或 OAuth 2.0 │
│ ✅ 实现权限控制 │
│ ✅ 验证资源所有权 │
│ │
│ 输入验证 │
│ ───────────────────────────────────────────── │
│ ✅ 验证所有输入 │
│ ✅ 使用参数化查询 │
│ ✅ 防止 SQL 注入 │
│ ✅ 防止 XSS 攻击 │
│ │
│ 速率限制 │
│ ───────────────────────────────────────────── │
│ ✅ 实现全局速率限制 │
│ ✅ 敏感端点加强限制 │
│ ✅ 返回限制信息 │
│ │
│ 敏感数据 │
│ ───────────────────────────────────────────── │
│ ✅ 不返回敏感字段 │
│ ✅ 日志脱敏 │
│ ✅ 错误信息不暴露实现细节 │
│ │
└─────────────────────────────────────────────────────────────┘
性能优化最佳实践 #
text
┌─────────────────────────────────────────────────────────────┐
│ 性能优化最佳实践 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 缓存 │
│ ───────────────────────────────────────────── │
│ ✅ 使用 ETag 验证缓存 │
│ ✅ 设置 Cache-Control 头 │
│ ✅ 支持 If-None-Match │
│ ✅ 支持 If-Modified-Since │
│ │
│ 压缩 │
│ ───────────────────────────────────────────── │
│ ✅ 启用 Gzip 压缩 │
│ ✅ 压缩 JSON 响应 │
│ │
│ 分页 │
│ ───────────────────────────────────────────── │
│ ✅ 默认分页 │
│ ✅ 限制最大返回数量 │
│ ✅ 使用游标分页处理大数据 │
│ │
│ 字段选择 │
│ ───────────────────────────────────────────── │
│ ✅ 支持字段选择 │
│ ✅ 减少不必要的数据传输 │
│ │
│ 连接优化 │
│ ───────────────────────────────────────────── │
│ ✅ 使用 HTTP/2 │
│ ✅ 启用 Keep-Alive │
│ ✅ 使用 CDN │
│ │
└─────────────────────────────────────────────────────────────┘
文档最佳实践 #
text
┌─────────────────────────────────────────────────────────────┐
│ 文档最佳实践 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 文档内容 │
│ ───────────────────────────────────────────── │
│ ✅ API 概述和认证方式 │
│ ✅ 端点列表和详细说明 │
│ ✅ 请求参数和响应格式 │
│ ✅ 状态码和错误码说明 │
│ ✅ 使用示例和代码片段 │
│ ✅ 变更日志 │
│ │
│ 文档工具 │
│ ───────────────────────────────────────────── │
│ ✅ 使用 OpenAPI/Swagger │
│ ✅ 提供交互式文档 │
│ ✅ 提供 SDK 和示例代码 │
│ │
│ 示例文档结构: │
│ - 快速开始 │
│ - 认证授权 │
│ - API 参考 │
│ - 错误处理 │
│ - 最佳实践 │
│ - 变更日志 │
│ │
└─────────────────────────────────────────────────────────────┘
版本管理最佳实践 #
text
┌─────────────────────────────────────────────────────────────┐
│ 版本管理最佳实践 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 版本策略 │
│ ───────────────────────────────────────────── │
│ ✅ 使用 URL 路径版本(推荐) │
│ ✅ 只使用主版本号 │
│ ✅ 保持版本策略一致 │
│ │
│ 版本变更 │
│ ───────────────────────────────────────────── │
│ ✅ 向后兼容优先 │
│ ✅ 提前发布废弃公告 │
│ ✅ 提供迁移指南 │
│ ✅ 设置合理的过渡期 │
│ │
│ 版本废弃 │
│ ───────────────────────────────────────────── │
│ ✅ 添加废弃警告 Header │
│ ✅ 响应中包含警告信息 │
│ ✅ 提供迁移时间表 │
│ ✅ 过期后返回 410 Gone │
│ │
└─────────────────────────────────────────────────────────────┘
检查清单 #
text
□ URL 设计
□ 使用名词表示资源
□ 使用复数形式
□ 使用小写字母和连字符
□ 层级不超过三层
□ HTTP 方法
□ GET 用于查询
□ POST 用于创建
□ PUT 用于完整更新
□ PATCH 用于部分更新
□ DELETE 用于删除
□ 状态码
□ 使用正确的状态码
□ 成功返回 2xx
□ 客户端错误返回 4xx
□ 服务端错误返回 5xx
□ 响应格式
□ 使用 JSON 格式
□ 属性使用 camelCase
□ 时间使用 ISO 8601
□ 列表包含分页信息
□ 安全
□ 使用 HTTPS
□ 实现认证授权
□ 验证输入
□ 实现速率限制
□ 性能
□ 支持缓存
□ 启用压缩
□ 默认分页
□ 支持字段选择
□ 文档
□ 提供完整文档
□ 包含使用示例
□ 说明错误码
□ 维护变更日志
□ 版本
□ 实现版本控制
□ 提供迁移指南
□ 发布废弃公告
下一步 #
现在你已经了解了 RESTful API 的最佳实践,接下来学习 高级主题,深入了解更复杂的 API 设计场景!
最后更新:2026-03-29