HTTP 请求方法选择与 RESTful 实践
(同时对比 GraphQL 和 RPC 风格)
这是后端接口设计中最常被问、也最容易踩坑的主题之一。下面用 2025–2026 年实际项目中最常见的视角,把它们放在一起对比,帮助你建立清晰的决策框架。
1. HTTP 方法的核心语义(RESTful 视角)
| HTTP 方法 | 幂等性 | 安全性 | 典型语义(RESTful 推荐用法) | 常见实际误用场景 | 2025–2026 项目中占比(粗估) |
|---|---|---|---|---|---|
| GET | 是 | 是 | 获取资源(只读) | 把搜索、过滤参数写在 body 里 | ~60–70% |
| POST | 否 | 否 | 创建资源、提交数据、触发非幂等操作 | 用于“查询”复杂条件(应优先 GET + query) | ~20–30% |
| PUT | 是 | 否 | 整体替换资源(完整覆盖) | 部分更新也用 PUT(应改用 PATCH) | ~3–8% |
| PATCH | 否/是* | 否 | 部分更新资源(JSON Patch / JSON Merge Patch) | 整个资源都传(浪费带宽 + 并发冲突风险高) | ~5–15%(逐年上升) |
| DELETE | 是 | 否 | 删除资源 | 软删除、逻辑删除也用 DELETE(争议较大) | ~3–8% |
| HEAD | 是 | 是 | 只返回响应头(常用于检查资源是否存在/修改时间) | 极少用 | <1% |
| OPTIONS | 是 | 是 | 预检请求 / 描述资源支持的方法 | 浏览器 CORS 自动发,几乎不用手写 | 自动产生 |
幂等性:多次请求对服务器状态的影响与一次相同
安全性:请求不应该改变服务器状态(GET/HEAD/OPTIONS 应安全)
2. RESTful 资源设计时的典型方法选择表
| 操作类型 | 推荐 HTTP 方法 | URL 示例 | body 是否必须 | 备注与注意事项 |
|---|---|---|---|---|
| 获取单个资源 | GET | /users/123 | 否 | 优先 query string 传筛选条件 |
| 获取资源列表 | GET | /users 或 /users?role=admin | 否 | 复杂过滤 → query 或 POST(争议) |
| 创建资源 | POST | /users | 是 | 返回 201 + Location 头 |
| 整体替换资源 | PUT | /users/123 | 是 | 必须传完整资源 |
| 部分更新资源 | PATCH | /users/123 | 是 | JSON Patch 格式最规范 |
| 删除资源 | DELETE | /users/123 | 否/可选 | 软删除建议用 PATCH(is_deleted=true) |
| 批量操作 | POST | /users/batch-delete 或 /batch | 是 | RESTful 不鼓励批量,但现实中常见 |
| 触发动作(非 CRUD) | POST | /orders/456/ship 或 /posts/789/like | 视情况 | RPC 风格常见做法 |
| 搜索(复杂条件) | GET / POST | GET /search 或 POST /search | POST 时是 | 大厂多用 POST + body(避开 URL 长度限制) |
3. REST vs GraphQL vs RPC 风格对比(2025–2026 视角)
| 维度 | 经典 REST (HTTP 方法 + 资源路径) | GraphQL | RPC 风格(gRPC / JSON-RPC / POST 重度滥用) |
|---|---|---|---|
| 接口数量 | 较多(每个资源/子资源一个路径) | 极少(通常一个 /graphql 端点) | 极多(每个动作一个方法/路径) |
| 请求方式 | 语义化 HTTP 方法 | 几乎全 POST | 几乎全 POST |
| 响应字段控制 | 固定字段或字段过滤(?fields=) | 客户端精确声明需要字段 | 服务端决定全部返回 |
| 版本管理 | URL 版本(/v1/users)或 header | Schema 演进 + 弃用字段 | 方法名带版本(UserServiceV2) |
| 幂等性表达 | 天然支持(GET/PUT/DELETE) | 靠客户端自己保证 | 靠方法名约定(CreateUser vs UpsertUser) |
| 批量操作 | 较麻烦(需约定规范或子路径) | 原生支持(多个 mutation) | 天然支持(设计 BatchXXX 方法) |
| 移动端/弱网友好 | 中等 | 较好(减少冗余字段) | 中等–差(常返回超大响应) |
| 缓存友好度 | 高(GET 可缓存) | 较低(POST 不缓存) | 低 |
| 调试/文档友好 | Swagger / OpenAPI 很成熟 | GraphiQL / Apollo Studio 极强 | Swagger 也可,但不如前两者直观 |
| 2025–2026 项目占比 | ~50–60%(传统 CRUD 系统) | ~20–30%(BFF、复杂查询场景) | ~15–25%(内部系统、gRPC 微服务) |
4. 2025–2026 年真实项目中的折中选择趋势
| 项目类型 | 最常见组合方式 | 为什么这样选 |
|---|---|---|
| 传统管理后台 / 企业系统 | 经典 REST + OpenAPI | 工具链成熟、幂等性清晰 |
| 移动端 / 前后端分离 App | REST + 部分 POST 搜索 + GraphQL BFF | 减少请求次数、字段精确控制 |
| 微服务内部通信 | gRPC(RPC over HTTP/2) | 高性能、二进制、强类型 |
| 对外开放 API | RESTful + OpenAPI + 版本控制 | 生态最好、合作伙伴友好 |
| 复杂查询 + 多端聚合 | GraphQL(或 tRPC / Apollo Federation) | 客户端驱动、减少 over-fetching |
| 高并发写操作 | REST POST + 幂等性 token(或 RPC 风格) | 防止重复提交 |
5. 快速决策 checklist(面试/设计时可用)
问自己这 5 个问题:
- 这个接口是只读还是会修改状态?
→ 只读 → GET(尽量)
→ 修改 → POST / PUT / PATCH / DELETE - 幂等吗?多次调用结果是否相同?
→ 是 → 优先 PUT / DELETE
→ 否 → 用 POST - 需要客户端精确控制返回字段吗?
→ 是 → 考虑 GraphQL 或字段过滤
→ 否 → REST 够用 - 是对外 API 还是内部通信?
→ 对外 → REST + OpenAPI(或 GraphQL)
→ 内部 → gRPC / JSON-RPC 更高效 - 是否有批量/复杂动作需求?
→ 有 → POST + action 路径 或 GraphQL mutation
如果你正在设计某个具体接口(比如订单、用户、搜索、批量操作),可以告诉我业务场景,我可以帮你给出最推荐的 HTTP 方法 + 路径 + 状态码组合,以及是否值得引入 GraphQL。