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