Skip to content

理查森成熟度模型

本章导读:如何衡量一个 API "有多 REST"?Leonard Richardson 提出的成熟度模型(RMM)给出了一个广受欢迎的四级标尺。学完本章,你可以快速给自己的项目定级,并明确改进路线——每一级的提升都直接对应真实收益(可路由、可理解、可演进)。

1. 模型总览

理查森成熟度模型(Richardson Maturity Model)把 API 的 REST 化程度分为 0~3 级:

Level 3  超媒体控制(HATEOAS)        ← 像浏览器一样"发现"操作

Level 2  HTTP 资源与动词               ← 正确的 URI + 方法 + 状态码

Level 1  资源(Resources)             ← 把单体拆成多个端点

Level 0  沼泽(The Swamp)             ← 只有一个端点,全用 POST

该模型由 Leonard Richardson 在 2008 年提出,Martin Fowler 网站收录的专题文章《Richardson Maturity Model》是最广为流传的解读版本。

下面用一个博客场景的例子逐级演示。

2. Level 0:POX 沼泽

只有一个端点,所有请求都用 POST 发送,"做什么"完全写在报文里——HTTP 只是消息投递管道(Plain Old XML/JSON over HTTP):

http
POST /blog-service HTTP/1.1
Content-Type: application/json

{ "action": "publishArticle", "articleId": 42 }
http
POST /blog-service HTTP/1.1
Content-Type: application/json

{ "action": "listArticles", "authorId": 7, "page": 2 }

问题:

  • 网关、防火墙、缓存、监控对 URL 一无所知(全是同一个端点)。
  • 成功失败全靠私有字段约定,无法用状态码做通用处理。
  • API 行为没有公共标准可循,只能靠口口相传的文档。

Level 0 的改进方向:把动作拆到不同的资源端点上。

3. Level 1:资源

引入"资源"概念——为每类信息提供独立端点,并区分"单个资源"与"集合资源":

http
POST /articles/42/publish    ← 针对"文章 42"这个资源
POST /authors/7/articles     ← 针对"作者 7 的文章集合"

但此级别下方法仍是"随手用"的(常常全部 POST),状态码也基本只用 200。

收益: URL 开始具备可路由性与可理解性;资源建模倒逼团队思考领域结构。

改进方向:为操作选择正确的 HTTP 方法与状态码。

4. Level 2:HTTP 动词与状态码

这是现代 API 工程实践中**"RESTful"的默认水位线**。规则来自 RFC 9110:

4.1 方法映射到意图

http
GET    /articles/42          → 读取文章
POST   /articles             → 新建文章
PATCH  /articles/42          → 修改标题(局部更新)
DELETE /articles/42          → 删除文章

"发布"这类动词型操作有两种规范化处理:

http
# 方案 A:把状态当资源(推荐,PUT 幂等)
PUT /articles/42/status
Body: { "status": "published" }

# 方案 B:把"发布"建模为子资源(一次发布 = 创建一个发布记录)
POST /articles/42/publications

4.2 状态码表达结果

场景响应
找到文章200 OK + body
新建成功201 Created + Location: /articles/43
删除成功无内容204 No Content
文章不存在404 Not Found
未登录401 Unauthorized + WWW-Authenticate
已登录但无权限403 Forbidden
标题超长校验失败422 Unprocessable Content + 错误详情
并发编辑冲突409 Conflict412 Precondition Failed

4.3 Level 2 的自检清单

  • [ ] 读操作一律 GET(可缓存、可收藏、可预取)
  • [ ] 创建用 POST,返回 201 + Location
  • [ ] 全量替换用 PUT,局部修改用 PATCH
  • [ ] 删除用 DELETE,语义见 204/202/410 的取舍
  • [ ] 错误通过状态码区分,而不是 200 + code:-1

本教程第 02~05 篇的主体内容,就是教你把 Level 2 做扎实。

5. Level 3:超媒体驱动(HATEOAS)

Level 3 的要求:响应不仅包含数据,还包含"下一步可以做什么"的链接。客户端不需要硬编码 URL 模板,像浏览器点链接一样"发现" API:

json
GET /articles/42

{
  "id": 42,
  "title": "RESTful API 设计规范",
  "status": "draft",
  "_links": {
    "self":       { "href": "/articles/42" },
    "author":     { "href": "/authors/7" },
    "publish":    { "href": "/articles/42/status", "method": "PUT" },
    "comments":   { "href": "/articles/42/comments" },
    "delete":     { "href": "/articles/42", "method": "DELETE" }
  }
}

这是 Fielding 论文中"统一接口"约束的第四条:Hypermedia as the Engine of Application State(超媒体作为应用状态的引擎)。协议层的对应物是 RFC 8288 的 Link 头部,常见的 JSON 超媒体格式有 HAL、Siren、Collection+JSON。

真实收益(不只是优雅):

  • 服务端改 URL 结构时,只要继续返回正确的 _links,老客户端不受影响——URL 成为实现细节而非契约
  • 可以按用户权限动态裁剪可用操作:无删除权限的客户端,响应里干脆不出现 delete 链接。
  • API 具备自描述性,文档与探索工具(如 API 浏览器)可以自动遍历。

6. 各级别的取舍:一定要做到 Level 3 吗?

社区的主流态度是务实的:Level 2 是目标,Level 3 是可选项。

考量建议
内部系统、迭代快的团队Level 2 + OpenAPI 契约文档即可,HATEOAS 收益有限
对外平台型 API、版本包袱重值得投入 Level 3(如 GitHub 大量使用 Link 头做分页与关联发现)
面试/理论讨论记住 Fielding 的立场:不支持超媒体就不能叫 REST;工程上普遍称 Level 2 为 "RESTful"

7. 本章小结

  • RMM 是衡量 API "REST 化程度"的四级标尺:0 沼泽 → 1 资源 → 2 方法与状态码 → 3 超媒体。
  • 大多数团队的目标是把 Level 2 做彻底:方法语义正确、状态码丰富准确。
  • Level 3 的 HATEOAS 提供真正的解耦能力,可用 Link 头(RFC 8288)渐进式引入。

8. 下一步