首页技术专题博客目录我的收藏关于与联系

API 设计的那些坑:RESTful 不是万能的

项目初期,我们严格遵循 RESTful 规范设计 API。用了一年多,发现很多场景 RESTful 根本不适合。这篇文章聊聊 API 设计的实际问题,以及什么时候该用 RESTful,什么时候不该用。

为什么选了 RESTful?

项目初期,团队决定用 RESTful 设计 API。理由很充分:标准、简单、易理解。大家都学过,上手快。

刚开始确实不错,资源用名词,操作用 HTTP 方法,看起来很清晰。但用久了,问题就来了。

第一个坑:复杂查询

RESTful 的查询很简单,但我们的业务查询很复杂。比如要查询"最近 30 天注册的用户,按活跃度排序,只返回前 10 个"。

用 RESTful 的话,URL 会变成这样:

GET /users?registered_after=2025-03-05&sort_by=activity&limit=10

参数多了,URL 就变得很长。而且有些查询条件很复杂,用 query string 根本表达不了。

我们后来用了 GraphQL,复杂查询用 GraphQL,简单查询还是用 RESTful。

第二个坑:批量操作

RESTful 的批量操作很麻烦。比如要删除多个用户,RESTful 的做法是:

  • 发多个 DELETE 请求:慢,而且不是原子操作
  • 用 POST /users/batch-delete:不符合 RESTful 规范
  • 用 PATCH /users:语义不清晰

我们最后用了 POST /users/batch,虽然不符合 RESTful,但至少能用。

第三个坑:动作型操作

有些操作不是 CRUD,而是动作。比如"发送邮件"、"导出报表"、"重置密码"。

用 RESTful 的话,要这样设计:

  • POST /emails:发送邮件
  • POST /reports/export:导出报表
  • POST /users/:id/reset-password:重置密码

虽然能用,但总觉得别扭。这些操作不是创建资源,而是执行动作。

我们后来用了 RPC 风格的 API,动作型操作用 POST /rpc/send-email 这样的格式。

第四个坑:版本管理

RESTful 的版本管理是个问题。URL 里加版本号(/v1/users)还是 Header 里加版本号(Accept: application/vnd.api+json;version=1)?

我们选了 URL 版本号,因为简单直接。但问题来了,版本多了,URL 就乱了。

而且有些 API 要同时支持多个版本,代码就变得很复杂。

第五个坑:错误处理

RESTful 的错误处理用 HTTP 状态码,但业务错误怎么表示?

我们试过几个方案:

  • 用 HTTP 状态码:但业务错误很多,状态码不够用
  • 用错误码:在响应体里加 error_code,但每个客户端都要解析
  • 用错误对象:统一错误格式,但实现复杂

最后统一了错误格式,所有错误都返回 200,错误信息在响应体里。虽然不符合 RESTful,但至少统一。

我们的解决方案

用了一年多 RESTful,我们发现:

  • CRUD 操作用 RESTful,简单清晰
  • 复杂查询用 GraphQL,灵活强大
  • 动作型操作用 RPC 风格,语义明确
  • 批量操作用自定义端点,实用优先

不是所有 API 都要 RESTful,看场景选方案。

API 设计的经验

做了几年 API 设计,总结几个经验:

1. 一致性比规范重要

整个 API 要保持一致的风格,比严格遵循某个规范更重要。如果有些 API 不符合 RESTful,但风格一致,也能接受。

2. 实用优先

API 是给人用的,不是给规范用的。如果 RESTful 不适合,就用其他方案。实用优先,规范其次。

3. 文档要清晰

API 文档要清晰,参数、返回值、错误码都要说明。我们用了 OpenAPI(Swagger),自动生成文档,方便很多。

4. 版本管理要早规划

API 版本管理要早规划,不然后面改起来很麻烦。我们一开始没规划,后来改 API 就很痛苦。

如果重新开始

如果重新设计 API,我会:

  • CRUD 用 RESTful,简单清晰
  • 复杂查询用 GraphQL 或自定义查询语言
  • 动作型操作用 RPC 风格
  • 统一错误格式和版本管理
  • 做好文档和测试

总结

RESTful 不是银弹,不是所有 API 都适合 RESTful。看场景选方案,实用优先。

如果你们的 API 设计也有问题,建议先看业务场景,再选技术方案。不要为了 RESTful 而 RESTful,实用最重要。

另外,API 设计要早规划,不然后面改起来很麻烦。我们吃过这个亏,后来花了很多时间才理清楚。

评论区