RESTful API 高级主题 #
概述 #
本章介绍 RESTful API 设计的高级主题,帮助开发者处理更复杂的业务场景。
text
┌─────────────────────────────────────────────────────────────┐
│ 高级主题概览 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ HATEOAS │ │ 异步操作 │ │ 批量操作 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 文件处理 │ │ GraphQL │ │ 实时通信 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
HATEOAS #
什么是 HATEOAS? #
text
┌─────────────────────────────────────────────────────────────┐
│ HATEOAS 概念 │
├─────────────────────────────────────────────────────────────┤
│ │
│ HATEOAS = Hypermedia as the Engine of Application State │
│ 超媒体作为应用状态引擎 │
│ │
│ 核心思想: │
│ 客户端通过服务端返回的超媒体链接发现可执行的操作 │
│ 而不需要预先知道所有 URL │
│ │
│ 优势: │
│ ✅ 客户端无需硬编码 URL │
│ ✅ API 可动态演进 │
│ ✅ 自描述能力 │
│ ✅ 降低客户端复杂度 │
│ │
└─────────────────────────────────────────────────────────────┘
HATEOAS 实现示例 #
text
┌─────────────────────────────────────────────────────────────┐
│ HATEOAS 实现示例 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 请求: │
│ GET /orders/123 │
│ │
│ 响应: │
│ { │
│ "id": 123, │
│ "status": "pending", │
│ "total": 1000, │
│ "items": [...], │
│ "_links": { │
│ "self": { │
│ "href": "/orders/123", │
│ "method": "GET" │
│ }, │
│ "update": { │
│ "href": "/orders/123", │
│ "method": "PUT" │
│ }, │
│ "cancel": { │
│ "href": "/orders/123/cancel", │
│ "method": "POST" │
│ }, │
│ "pay": { │
│ "href": "/orders/123/payments", │
│ "method": "POST" │
│ }, │
│ "user": { │
│ "href": "/users/456" │
│ } │
│ } │
│ } │
│ │
│ 根据订单状态,返回不同的可用操作: │
│ - pending: 可支付、可取消 │
│ - paid: 可发货 │
│ - shipped: 可确认收货 │
│ - completed: 无操作 │
│ │
└─────────────────────────────────────────────────────────────┘
HAL 格式 #
text
┌─────────────────────────────────────────────────────────────┐
│ HAL 格式 │
├─────────────────────────────────────────────────────────────┤
│ │
│ HAL(Hypertext Application Language) │
│ 一种标准的超媒体格式 │
│ │
│ 响应示例: │
│ { │
│ "_links": { │
│ "self": { "href": "/orders/123" }, │
│ "next": { "href": "/orders/124" }, │
│ "prev": { "href": "/orders/122" } │
│ }, │
│ "_embedded": { │
│ "user": { │
│ "_links": { │
│ "self": { "href": "/users/456" } │
│ }, │
│ "name": "张三" │
│ } │
│ }, │
│ "id": 123, │
│ "status": "pending" │
│ } │
│ │
└─────────────────────────────────────────────────────────────┘
异步操作 #
长时间运行的操作 #
text
┌─────────────────────────────────────────────────────────────┐
│ 异步操作处理 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 场景: │
│ - 大文件导入 │
│ - 报表生成 │
│ - 批量数据处理 │
│ - 视频转码 │
│ │
│ 流程: │
│ │
│ 1. 创建异步任务 │
│ POST /imports │
│ { "fileUrl": "https://..." } │
│ │
│ 响应: │
│ HTTP/1.1 202 Accepted │
│ Location: /imports/abc123 │
│ │
│ { │
│ "id": "abc123", │
│ "status": "pending", │
│ "progress": 0, │
│ "createdAt": "2025-03-29T10:00:00Z", │
│ "_links": { │
│ "self": { "href": "/imports/abc123" }, │
│ "cancel": { "href": "/imports/abc123/cancel" } │
│ } │
│ } │
│ │
│ 2. 查询任务状态 │
│ GET /imports/abc123 │
│ │
│ 响应: │
│ { │
│ "id": "abc123", │
│ "status": "processing", │
│ "progress": 45, │
│ "startedAt": "2025-03-29T10:00:05Z", │
│ "estimatedCompletion": "2025-03-29T10:05:00Z" │
│ } │
│ │
│ 3. 任务完成 │
│ GET /imports/abc123 │
│ │
│ 响应: │
│ { │
│ "id": "abc123", │
│ "status": "completed", │
│ "progress": 100, │
│ "completedAt": "2025-03-29T10:04:30Z", │
│ "result": { │
│ "imported": 1000, │
│ "failed": 5, │
│ "reportUrl": "/imports/abc123/report" │
│ } │
│ } │
│ │
└─────────────────────────────────────────────────────────────┘
任务状态管理 #
text
┌─────────────────────────────────────────────────────────────┐
│ 任务状态管理 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 状态流转: │
│ │
│ pending → processing → completed │
│ │ │ │
│ │ └──→ failed │
│ │ │
│ └──→ cancelled │
│ │
│ 状态说明: │
│ - pending:等待处理 │
│ - processing:处理中 │
│ - completed:已完成 │
│ - failed:失败 │
│ - cancelled:已取消 │
│ │
│ 任务端点设计: │
│ GET /tasks 任务列表 │
│ GET /tasks/{id} 任务详情 │
│ POST /tasks/{id}/cancel 取消任务 │
│ DELETE /tasks/{id} 删除任务 │
│ │
└─────────────────────────────────────────────────────────────┘
批量操作 #
批量创建 #
text
┌─────────────────────────────────────────────────────────────┐
│ 批量创建 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 请求: │
│ POST /users/batch │
│ Content-Type: application/json │
│ │
│ { │
│ "users": [ │
│ { "name": "用户1", "email": "user1@example.com" }, │
│ { "name": "用户2", "email": "user2@example.com" }, │
│ { "name": "用户3", "email": "invalid-email" } │
│ ] │
│ } │
│ │
│ 响应: │
│ HTTP/1.1 207 Multi-Status │
│ │
│ { │
│ "results": [ │
│ { │
│ "index": 0, │
│ "status": 201, │
│ "data": { "id": 1, "name": "用户1" } │
│ }, │
│ { │
│ "index": 1, │
│ "status": 201, │
│ "data": { "id": 2, "name": "用户2" } │
│ }, │
│ { │
│ "index": 2, │
│ "status": 400, │
│ "error": { │
│ "code": "INVALID_EMAIL", │
│ "message": "Invalid email format" │
│ } │
│ } │
│ ], │
│ "summary": { │
│ "total": 3, │
│ "succeeded": 2, │
│ "failed": 1 │
│ } │
│ } │
│ │
└─────────────────────────────────────────────────────────────┘
批量更新和删除 #
text
┌─────────────────────────────────────────────────────────────┐
│ 批量更新和删除 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 批量更新: │
│ PATCH /users/batch │
│ { │
│ "ids": [1, 2, 3], │
│ "updates": { │
│ "status": "active" │
│ } │
│ } │
│ │
│ 响应: │
│ { │
│ "updated": 3, │
│ "ids": [1, 2, 3] │
│ } │
│ │
│ 批量删除: │
│ DELETE /users/batch?ids=1,2,3 │
│ │
│ 或 │
│ │
│ POST /users/batch-delete │
│ { │
│ "ids": [1, 2, 3] │
│ } │
│ │
│ 响应: │
│ { │
│ "deleted": 3, │
│ "ids": [1, 2, 3] │
│ } │
│ │
└─────────────────────────────────────────────────────────────┘
文件处理 #
文件上传 #
text
┌─────────────────────────────────────────────────────────────┐
│ 文件上传 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 单文件上传: │
│ POST /uploads │
│ Content-Type: multipart/form-data │
│ │
│ file: [binary data] │
│ │
│ 响应: │
│ { │
│ "id": "file-abc123", │
│ "url": "https://cdn.example.com/files/file-abc123.jpg", │
│ "filename": "photo.jpg", │
│ "mimeType": "image/jpeg", │
│ "size": 102400, │
│ "createdAt": "2025-03-29T10:00:00Z" │
│ } │
│ │
│ 大文件分片上传: │
│ 1. 初始化上传 │
│ POST /uploads/init │
│ { │
│ "filename": "large-video.mp4", │
│ "mimeType": "video/mp4", │
│ "size": 1073741824 │
│ } │
│ │
│ 响应: │
│ { │
│ "uploadId": "upload-xyz", │
│ "chunkSize": 5242880, │
│ "totalChunks": 205 │
│ } │
│ │
│ 2. 上传分片 │
│ PUT /uploads/upload-xyz/chunks/1 │
│ Content-Type: application/octet-stream │
│ │
│ [chunk data] │
│ │
│ 3. 完成上传 │
│ POST /uploads/upload-xyz/complete │
│ │
└─────────────────────────────────────────────────────────────┘
文件下载 #
text
┌─────────────────────────────────────────────────────────────┐
│ 文件下载 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 下载文件: │
│ GET /files/file-abc123 │
│ │
│ 响应: │
│ HTTP/1.1 200 OK │
│ Content-Type: image/jpeg │
│ Content-Disposition: attachment; filename="photo.jpg" │
│ Content-Length: 102400 │
│ │
│ [binary data] │
│ │
│ 范围请求(断点续传): │
│ GET /files/file-abc123 │
│ Range: bytes=0-1023 │
│ │
│ 响应: │
│ HTTP/1.1 206 Partial Content │
│ Content-Range: bytes 0-1023/102400 │
│ Content-Length: 1024 │
│ │
│ [partial data] │
│ │
└─────────────────────────────────────────────────────────────┘
REST vs GraphQL #
对比分析 #
text
┌─────────────────────────────────────────────────────────────┐
│ REST vs GraphQL │
├─────────────────────────────────────────────────────────────┤
│ │
│ REST │
│ ───────────────────────────────────────────── │
│ 优点: │
│ ✅ 简单直观 │
│ ✅ 标准化 │
│ ✅ 缓存友好 │
│ ✅ 工具成熟 │
│ │
│ 缺点: │
│ ❌ 可能需要多次请求 │
│ ❌ 可能返回多余数据 │
│ ❌ 灵活性较低 │
│ │
│ GraphQL │
│ ───────────────────────────────────────────── │
│ 优点: │
│ ✅ 单次请求获取所需数据 │
│ ✅ 按需获取字段 │
│ ✅ 类型系统 │
│ ✅ 实时文档 │
│ │
│ 缺点: │
│ ❌ 学习曲线陡峭 │
│ ❌ 缓存复杂 │
│ ❌ 安全性挑战 │
│ ❌ 可能导致复杂查询 │
│ │
└─────────────────────────────────────────────────────────────┘
选择建议 #
text
┌─────────────────────────────────────────────────────────────┐
│ 选择建议 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 选择 REST 的场景: │
│ - 资源结构清晰 │
│ - 需要良好的缓存支持 │
│ - 团队熟悉 REST │
│ - 公开 API │
│ - 微服务架构 │
│ │
│ 选择 GraphQL 的场景: │
│ - 复杂的数据关系 │
│ - 需要灵活查询 │
│ - 前端驱动开发 │
│ - 内部 API │
│ - 需要聚合多个数据源 │
│ │
│ 混合方案: │
│ - 核心资源使用 REST │
│ - 复杂查询使用 GraphQL │
│ │
└─────────────────────────────────────────────────────────────┘
实时通信 #
WebSocket 集成 #
text
┌─────────────────────────────────────────────────────────────┐
│ WebSocket 集成 │
├─────────────────────────────────────────────────────────────┤
│ │
│ REST API 用于常规操作,WebSocket 用于实时更新 │
│ │
│ 场景: │
│ - 实时通知 │
│ - 聊天消息 │
│ - 协作编辑 │
│ - 实时数据 │
│ │
│ 设计模式: │
│ │
│ 1. REST API 创建资源 │
│ POST /messages │
│ { "content": "Hello" } │
│ │
│ 2. WebSocket 推送更新 │
│ ws://api.example.com/ws │
│ │
│ 消息格式: │
│ { │
│ "event": "message.created", │
│ "data": { │
│ "id": 123, │
│ "content": "Hello", │
│ "createdAt": "2025-03-29T10:00:00Z" │
│ } │
│ } │
│ │
└─────────────────────────────────────────────────────────────┘
Server-Sent Events #
text
┌─────────────────────────────────────────────────────────────┐
│ Server-Sent Events │
├─────────────────────────────────────────────────────────────┤
│ │
│ 单向实时推送,适合服务端主动推送场景 │
│ │
│ 端点设计: │
│ GET /events │
│ Accept: text/event-stream │
│ │
│ 响应: │
│ HTTP/1.1 200 OK │
│ Content-Type: text/event-stream │
│ Cache-Control: no-cache │
│ Connection: keep-alive │
│ │
│ data: {"event": "notification", "message": "New order"} │
│ │
│ data: {"event": "update", "resource": "order", "id": 123} │
│ │
└─────────────────────────────────────────────────────────────┘
总结 #
text
┌─────────────────────────────────────────────────────────────┐
│ 高级主题总结 │
├─────────────────────────────────────────────────────────────┤
│ │
│ HATEOAS │
│ - 提供超媒体链接 │
│ - 实现自描述 API │
│ - 降低客户端耦合 │
│ │
│ 异步操作 │
│ - 返回 202 Accepted │
│ - 提供任务状态查询 │
│ - 支持取消操作 │
│ │
│ 批量操作 │
│ - 支持批量创建、更新、删除 │
│ - 返回详细结果 │
│ - 使用 207 Multi-Status │
│ │
│ 文件处理 │
│ - 支持分片上传 │
│ - 支持范围请求 │
│ - 返回文件元数据 │
│ │
│ 技术选型 │
│ - REST vs GraphQL 根据场景选择 │
│ - 实时通信使用 WebSocket 或 SSE │
│ │
└─────────────────────────────────────────────────────────────┘
学习路径回顾 #
text
入门阶段
├── REST API 简介
├── RESTful 设计原则
└── 资源设计
进阶阶段
├── 端点设计
├── HTTP 方法使用
├── 状态码使用
└── API 版本管理
高级阶段
├── API 安全
├── 分页与过滤
├── 错误处理
└── 最佳实践
扩展阶段
└── 高级主题(本文)
恭喜你完成了 RESTful API 设计的学习!现在你已经具备了设计高质量 RESTful API 的能力。
最后更新:2026-03-29