由 Leonard Richardson 提出的 Richardson 成熟度模型 (RMM) 是一种用于根据 API 的实现级别来评估其 RESTful 成熟度的模型。它包含四个级别,每个级别都代表了 RESTful 原则在设计与实现中的成熟阶段。在这篇文章中,我们将深入探讨每一个级别,并结合 2026 年的开发实践,看看我们是如何在实际项目中评估和升级我们的 API 架构的。
在确定服务的成熟度时,Richardson 强调了三个主要因素。它们包括:
- URI
- HTTP 方法
- HATEOAS (超媒体)
虽然这些概念已经存在了很长时间,但在 AI 辅助编程和云原生架构普及的今天,重新审视它们对于我们构建健壮的系统至关重要。
目录
目录
- URI
- HTTP 方法
- HATEOAS
- 级别 0:POX 的沼泽
- 级别 1:资源
- 级别 2:HTTP 动词
- 级别 3:超媒体控制 (HATEOAS)
- 2026 视角:为何级别 3 依然困难?
- 工程化实践:从设计到部署
- AI 辅助开发:现代 API 开发工作流
- 实现方法
URI
统一资源标识符 (URI) 是 Web 技术用于标识 Web 上资源的一串唯一字符序列。在 2026 年,我们设计 URI 时,不仅仅要考虑唯一性,还要考虑到“可预测性”和“AI 友好性”。
你会发现,当你的 URI 结构足够清晰时,像 Cursor 或 GitHub Copilot 这样的 AI 编程助手能更准确地理解你的资源关系,从而生成更精确的代码补全。
HTTP 方法
超文本传输协议 (HTTP) 是一种用于传输超媒体文档的协议。虽然我们都熟悉这些方法,但在生产环境中,正确使用它们的语义往往比看起来要复杂得多。
- GET: 安全且幂等。我们不仅用它来获取数据,还会利用 INLINECODE2a07bf9b 和 INLINECODEfde6551b 头来实现高效的缓存策略,减少服务器负载。
- POST: 非幂等。我们通常用于创建子资源或启动一个处理流程。在现代 API 中,
POST也可以用来触发一个复杂的异步任务。 - PUT: 幂等。我们用它来替换资源的全量表示。切记,如果客户端只传递了部分字段,不要用
PUT,这可能会导致未传递的字段被意外清空。 - PATCH: 部分更新。这是我们处理资源局部更新的首选,例如仅修改用户的邮箱地址。但要注意处理并发冲突。
- DELETE: 幂等。用于删除资源。在实际生产中,我们通常实行“软删除”(Soft Delete),即不物理删除数据,而是标记为已删除,以便于数据恢复和审计。
HATEOAS
HATEOAS(超媒体作为应用状态引擎)是 REST 最具争议也最核心的部分。它意味着“可发现性”。客户端可以仅通过服务器的响应与 REST API 进行交互。这是一种自文档化的超媒体。客户端在交互新 API 时无需查阅任何文档(或者文档极少)。
REST 服务根据 Richardson 成熟度模型划分为不同的成熟度级别。 让我们看看你的 API 目前处于哪个阶段。
级别 0:POX 的沼泽
这是最原始的阶段。坦白说,如果你在维护一个遗留系统,你很可能见过这种场景。
特征:
- 使用 HTTP 作为传输协议,但并未利用其特性。
- 通常依赖单一的端点(例如
POST /api)来处理所有操作。 - 将 HTTP 视为远程过程调用 (RPC) 的隧道,只是在 HTTP 上包装了 XML 或 JSON。
主要问题:
- 缺乏语义:状态码通常全是 200 OK,错误信息藏在 body 里。
- 难以缓存:因为一切操作都是 POST,HTTP 缓存中间件完全无法工作。
- 客户端重:客户端必须“知道”所有的 URL 结构。
级别 1:资源
在这个阶段,我们开始意识到“万物皆资源”。
特征:
- 引入了“资源”的概念作为关键抽象。
- 资源通过独立的 URL 暴露(例如 INLINECODE010a4d20、INLINECODE0e437205)。
主要问题:
虽然 URI 设计得不错,但很多开发者在这个阶段容易犯一个错误:动作滥用。例如,使用 INLINECODE246d2538 而不是 INLINECODEb3e3dbfc。这表明你虽然在处理资源,但还没有充分利用 HTTP 协议的动词。
级别 2:HTTP 动词
这是我们绝大多数“现代化” API 所处的阶段,也是许多开发者认为的“足够好”的阶段。
特征:
- 正确使用 GET、POST、PUT、DELETE。
- 利用 HTTP 标头进行内容协商(如
Accept: application/json)。 - 使用标准的状态码(200, 201, 204, 400, 401, 403, 404, 500)。
主要优势:
- 可缓存性:GET 请求可以被网关和浏览器缓存,极大提升性能。
- 统一接口:一旦前端开发者理解了这套规则,任何新的资源接口都能秒懂。
级别 3:超媒体控制 (HATEOAS)
这是 REST 的“圣杯”。虽然在这个 GraphQL 和 tRPC 大行其道的年代,HATEOAS 看起来有些古老,但在解耦服务端和客户端方面,它依然有着不可替代的优势。
特征:
在响应体中,除了数据本身,还包含了下一步可以做什么的链接(Links)。
代码示例:HATEOAS 风格的响应
// 获取用户信息的响应
{
"id": "u-123",
"name": "Alex Chen",
"role": "editor",
"_links": {
"self": { "href": "/users/u-123" },
"update": { "href": "/users/u-123", "method": "PUT" },
"delete": { "href": "/users/u-123", "method": "DELETE" },
"articles": { "href": "/users/u-123/articles" }
},
"_embedded": {
"latest_article": {
"id": "a-999",
"title": "2026 AI Trends",
"_links": {
"self": { "href": "/articles/a-999" }
}
}
}
}
主要优势:
- 解耦:服务端修改 URL 结构时,不需要破坏旧版本的客户端,因为客户端是动态读取链接的。
- 状态机:API 变成了一个状态机,客户端根据当前状态和提供的链接决定下一步动作,无需硬编码逻辑。
2026 视角:为何级别 3 依然困难?
你可能会问,既然 HATEOAS 这么好,为什么我们在大部分项目中很少见到它?
在我们的经验中,主要原因在于开发范式的不匹配。前端开发者习惯于强类型接口(如 TypeScript 的 interface),他们希望在编写代码时就能获得智能提示。而 HATEOAS 的动态特性使得传统的静态类型检查变得困难。
但是,2026 年的技术栈正在改变这一现状。
随着 Agentic AI 的发展,未来的客户端可能不再是由人类硬编码的静态前端代码,而是能够理解超媒体、自主导航 API 的 AI 代理。对于 AI Agent 来说,HATEOAS 是最自然的交互方式——它不需要死记硬背 URL,只需像人类浏览网页一样“点击”链接即可。这使得级别 3 在 AI 原生应用时代迎来了复苏的契机。
工程化实践:从设计到部署
让我们聊聊如何将 RMM 模型应用到实际的工程生产中。我们不仅要设计 API,还要保证它的高可用和可维护性。
1. 生产级代码示例:Level 2 API 实现
我们来看一个使用 Node.js 和 Express 构建的实际例子。我们将展示如何处理内容协商和正确的状态码。
const express = require(‘express‘);
const app = express();
app.use(express.json());
// 模拟数据库
let articles = [{ id: 1, title: ‘RMM Explained‘, content: ‘...‘ }];
// GET /articles - 获取列表 (支持分页)
app.get(‘/api/articles‘, (req, res) => {
const { page = 1, limit = 10 } = req.query;
// 使用 Set 添加 Link 头,实现简单的分页导航(即使未完全达到 Level 3,这也是个好习惯)
res.setHeader(‘Link‘, ‘; rel="next"‘);
res.status(200).json({
data: articles.slice(0, limit),
meta: { page, limit, total: articles.length }
});
});
// POST /articles - 创建资源
app.post(‘/api/articles‘, (req, res) => {
if (!req.body.title) {
// 使用 400 状态码表示客户端错误
return res.status(400).json({ error: ‘Title is required‘ });
}
const newArticle = {
id: articles.length + 1,
title: req.body.title,
content: req.body.content || ‘‘
};
articles.push(newArticle);
// 使用 201 Created 状态码,并在 Header 中返回 Location
res.location(`/api/articles/${newArticle.id}`).status(201).json(newArticle);
});
// DELETE /articles/:id - 删除资源
app.delete(‘/api/articles/:id‘, (req, res) => {
const articleId = parseInt(req.params.id);
const index = articles.findIndex(a => a.id === articleId);
if (index === -1) {
// 404 Not Found 比 200 OK (with success: false) 更符合 HTTP 语义
return res.status(404).json({ error: ‘Article not found‘ });
}
articles.splice(index, 1);
// 204 No Content 表示操作成功且无返回体
res.status(204).send();
});
module.exports = app;
2. 故障排查与调试技巧
在我们最近的一个项目中,遇到了一个非常棘手的问题:客户端偶尔报告收到 403 Forbidden,但这并不符合我们的权限逻辑。
排查过程:
- 检查 HTTP 动词:我们发现运维人员在配置 Nginx 反向代理时,错误地拦截了某些
PUT请求。 - 监控工具:我们使用了 Grafana Loki 来聚合日志。通过查询
trace_id,我们定位到了是网关层而非应用层返回的错误。
经验总结:在微服务架构中,当你遇到奇怪的 HTTP 状态码时,第一反应不应该是查代码,而是检查网关配置和CORS 策略。很多时候,Level 0 或 Level 1 的问题并非来自代码本身,而是基础设施配置不当。
3. 性能优化:HATEOAS 的代价
实现 Level 3 会带来额外的序列化开销。如果你在响应中嵌入了太多关联资源的链接和数据,可能会导致响应体膨胀。
解决方案:
- 字段投影:允许客户端使用 INLINECODE39b8ffa1 参数指定需要的字段(例如 INLINECODE444bd4aa)。
- 数据分片:不要在
_embedded中返回所有子资源,只返回摘要或链接。
AI 辅助开发:现代 API 开发工作流
到了 2026 年,如果你还在手写所有的 CRUD 增删改查代码,你可能就落伍了。我们现在的开发流程已经深度融合了 AI 工具,这被称为 Vibe Coding(氛围编程)。
使用 Cursor 或 Windsurf 加速开发
当我们需要构建一个新的资源端点时,我们通常这样与 AI 协作:
- 自然语言定义规范:我们在 IDE 中写下注释:
// Create a RESTful endpoint for /api/orders
// Level 2 Maturity: Use GET, POST, PUT, DELETE
// Implement validation for order status (pending, shipped, delivered)
// Return proper HTTP status codes
LLM 驱动的测试
我们甚至可以要求 AI 生成边界测试用例。例如,告诉 AI:“测试当库存不足时,INLINECODE8c8a76e6 应该返回 INLINECODE3265b1c2 而不是 500 Error”。AI 能够根据描述生成高质量的集成测试代码,这对于维护 API 的稳定性至关重要。
实现方法
回到基础。为了亲手体验 RMM 的各个层级,我们将创建一个名为 wiki-demo 的 RESTful API。我们将插入文章并发送 HTTP 请求。在此过程中,我们将获取、修改和删除文章。
我们将使用 Robo3T 作为数据库,使用 Postman 发送请求。为了在 Node.js 中创建 RESTful API,我们需要安装以下工具(注:Robo3T 现已更名为 MongoDB Compass,但我们依然习惯这种轻量级的交互):
- node: 一个 JavaScript 运行时环境,下载链接:https://nodejs.org/en/download/
- MongoDB Compass/Robo3t: 一个 MongoDB GUI。我们将使用它创建数据库,下载链接:https://www.mongodb.com/try/download/compass
- Postman: 一个 API 开发和测试平台,下载链接:https://www.postman.com/
- Visual Studio Code 或 (任何代码编辑器),下载链接:https://code.visualstudio.com/download (推荐安装 Cursor 扩展以体验 AI 辅助)
- JSON Viewer Pro Chrome 扩展程序,下载链接:https://chromewebstore.google
安装步骤
- 初始化项目:
mkdir wiki-demo-rmm
cd wiki-demo-rmm
npm init -y
npm install express mongoose body-parser
- 启动服务器 (server.js):
让我们编写一个简单的服务器,从 Level 0 演进到 Level 2。
const express = require(‘express‘);
const mongoose = require(‘mongoose‘);
const app = express();
// 连接 MongoDB
mongoose.connect(‘mongodb://localhost:27017/wiki-demo‘)
.then(() => console.log(‘MongoDB Connected‘))
.catch(err => console.error(err));
// 定义 Schema
const ArticleSchema = new mongoose.Schema({
title: String,
content: String
});
const Article = mongoose.model(‘Article‘, ArticleSchema);
app.use(express.json());
// Level 2: 定义资源路由
// GET 获取所有文章
app.get(‘/articles‘, async (req, res) => {
const articles = await Article.find();
res.json(articles);
});
// POST 创建新文章
app.post(‘/articles‘, async (req, res) => {
const newArticle = new Article(req.body);
await newArticle.save();
res.status(201).json(newArticle);
});
// 启动服务
app.listen(3000, () => {
console.log(‘Server running on port 3000‘);
});
- 使用 Postman 测试:
– 设置请求为 POST http://localhost:3000/articles。
– 在 Body 中选择 INLINECODEd0095e1c 和 INLINECODEc874876a,输入 {"title": "RESTful 2026", "content": "..."}。
– 发送请求,你应该会收到 201 Created 响应和创建的对象。
结语:未来展望
Richardson 成熟度模型不仅仅是一个理论工具,它是我们设计 API 时的指南针。虽然大多数系统停留在 Level 2,但了解 Level 3 (HATEOAS) 对于构建真正解耦、面向未来的长期系统至关重要。随着 AI Agent 的普及,那些具备良好超媒体控制的 Level 3 API 将更容易被机器理解和使用。在接下来的文章中,我们将深入探讨如何在 GraphQL 的冲击下,依然保持 REST 的核心竞争力。
让我们一起构建更优雅的 API 吧!