北京时间:2026年4月9日
开篇引入

对于一名后端开发工程师或技术面试备考者而言,RESTful API几乎是绕不开的核心知识点。它不仅是前后端分离架构下的通信标准,更是微服务、云原生等现代技术体系的基石。许多开发者在日常工作中习惯于“能用就行”,对RESTful API的理解停留在表面——会用 GET 和 POST,却不明白什么是无状态;接口命名随意,状态码乱用,面试时被问到“什么是真正的RESTful”就支支吾吾。本文将通过浩瀚ai助手的系统梳理,从痛点切入、到概念讲解、再到代码演示和面试要点,帮你建立完整的知识链路。
一、痛点切入:为什么需要RESTful API

传统方式的典型实现
在 REST 架构出现之前,许多 Web 服务的接口设计缺乏统一规范,常见做法如下:
// 传统RPC风格的接口设计 GET /getUserById?id=123 GET /deleteUser?id=123 POST /createUser POST /updateUser // 或者更极端:所有操作都走同一个POST接口 POST /api?action=getUser&id=123 POST /api?action=deleteUser&id=123 POST /api?action=createUser
传统方式的痛点
上述方式存在诸多问题:
接口命名混乱:
/getUser、/deleteUser、/updateUser——动作和资源混在一起,一个资源对应多个接口方法滥用:GET 请求被用来删除数据,违背 HTTP 协议语义;或者所有操作都塞进 POST,状态码形同虚设
缺乏统一标准:每个团队或项目有自己的命名风格,新人上手成本高,跨团队协作困难
状态管理混乱:服务端需要维护客户端会话状态,不利于水平扩展
RESTful API 的设计初衷
2000年,Roy Fielding 在其博士论文中提出了 REST(Representational State Transfer,表现层状态转移)架构风格-7。它并非一种技术框架,而是一组架构约束和原则,旨在通过统一的标准让 Web 服务更简洁、可扩展、易维护-23。遵循这些约束设计的 API,被称为 RESTful API。
二、REST 的六大核心原则
REST 架构定义了六条核心约束,必须全部满足才能称为真正的 RESTful 系统-1。
原则一:统一接口
所有资源通过统一的标识符(URI)访问,操作方式统一使用标准 HTTP 方法。这意味着:
客户端不需要额外约定就能理解如何与服务器交互-6
URI 只标识资源,HTTP 方法表达操作意图
每个响应包含足够的信息供客户端解析,无需额外上下文-1
原则二:无状态
服务器不保存客户端的上下文状态,每个请求必须包含处理该请求所需的所有信息-2。这意味着:
每个请求是完整且自足的,不依赖之前的请求-1
任何服务器节点都可以处理任意请求,天然支持水平扩展
缺点是无法在服务器端维护会话,需要客户端携带认证信息(如 JWT)-63
原则三:客户端-服务器分离
客户端负责用户界面交互,服务器负责数据存储和处理,二者职责分离-2。好处在于:
客户端和服务器可以独立演进,只要 API 契约不变-6
同一套后端 API 可以服务于 Web、移动端、第三方应用等多种客户端-2
安全性增强:客户端无法直接访问数据存储层
原则四:可缓存
响应必须明确声明是否可缓存以及缓存时长-1。合理利用缓存可以:
大幅减少重复请求,降低服务器负载
提升响应速度,改善用户体验-2
减少带宽消耗
原则五:分层系统
客户端通常无法区分是与终端服务器通信还是与中间代理通信-7。这种设计允许:
在客户端和服务器之间加入负载均衡器、代理、网关等中间层
每层只关心相邻层的通信,降低系统耦合
在不影响客户端的情况下进行架构调整和性能优化
原则六:按需代码(可选)
服务器可以临时扩展客户端功能,例如返回可执行代码(如 JavaScript 脚本)-1。这是唯一可选的约束,在实际应用中使用较少。
三、RESTful API vs HTTP API:概念辨析
很多开发者容易混淆这两个概念,这里做一个清晰对比:
| 维度 | HTTP API | RESTful API |
|---|---|---|
| 定义 | 任何通过 HTTP 协议通信的 API | 遵循 REST 架构约束的 HTTP API 子集 |
| 规范程度 | 无强制性规范 | 必须满足六大核心原则 |
| 资源导向 | 不一定 | 必须:URI 标识资源,HTTP 方法表达操作 |
| 典型问题 | 可能出现 GET 删除数据、200 藏错误等反模式 | 严格遵循状态码语义和 HTTP 方法语义 |
一句话总结:所有 RESTful API 都是 HTTP API,但不是所有 HTTP API 都是 RESTful API。
四、RESTful API 设计规范详解
一个规范的 RESTful API,需要从资源命名、HTTP 方法、状态码、版本控制等多个维度进行考量。
1. URI 设计规范
使用名词而非动词:URI 只标识资源,动作由 HTTP 方法表达-7。
❌ 错误: /api/getUsers /api/createUser /api/deleteUser/1 ✅ 正确: GET /api/users POST /api/users DELETE /api/users/1
使用复数名词表示集合:保持一致性,即使访问单个资源也用复数-6。
✅ 推荐: GET /api/users 获取所有用户 GET /api/users/123 获取 ID 为 123 的用户
层级结构表达从属关系:使用嵌套 URI 表示资源间的从属关系,但层级不宜过深(建议不超过 3 层)-7。
✅ 推荐:/api/users/123/orders 获取用户 123 的所有订单 ⚠️ 避免:/api/users/123/orders/456/items/789/details 过深
命名风格:统一使用小写字母,单词间用连字符 - 分隔,避免下划线-7。
✅ 推荐:/api/user-profiles ❌ 避免:/api/user_profiles ❌ 避免:/api/userProfiles
路径参数 vs 查询参数:
| 参数类型 | 用途 | 示例 |
|---|---|---|
| 路径参数 | 标识特定资源,必须提供 | GET /api/users/123 |
| 查询参数 | 过滤、排序、分页,可选 | GET /api/users?role=admin&page=2 |
2. HTTP 方法与状态码规范
标准 HTTP 方法:
| 方法 | 语义 | 集合资源(如 /users) | 成员资源(如 /users/1) | 幂等性 |
|---|---|---|---|---|
| GET | 获取资源 | 返回所有用户 | 返回指定用户 | ✅ 是 |
| POST | 创建资源 | 创建新用户 | 不适用 | ❌ 否 |
| PUT | 全量更新 | 不推荐 | 完全替换用户 | ✅ 是 |
| PATCH | 局部更新 | 不推荐 | 部分更新用户 | ❌ 否 |
| DELETE | 删除资源 | 清空集合 | 删除指定用户 | ✅ 是 |
HTTP 状态码语义分层:
2xx 成功类 ├── 200 OK:请求成功 ├── 201 Created:资源创建成功(POST 请求标准返回码) └── 204 No Content:请求成功但无返回内容(DELETE 常用) 4xx 客户端错误 ├── 400 Bad Request:请求参数错误或格式有误 ├── 401 Unauthorized:未认证,需要登录 ├── 403 Forbidden:已认证但无权限访问 ├── 404 Not Found:请求的资源不存在 └── 422 Unprocessable Entity:请求语法正确但语义校验失败 5xx 服务端错误 ├── 500 Internal Server Error:服务器内部错误 ├── 502 Bad Gateway:网关错误 └── 503 Service Unavailable:服务暂时不可用
⚠️ 常见误区:无论请求成功还是失败都返回 200,前端通过业务码判断。这种做法破坏了 HTTP 状态码的语义,增加了开发和调试的难度,不符合 RESTful 规范-。
3. 版本管理策略
API 需要迭代演进,如何在不破坏现有客户端的情况下引入破坏性变更?主流策略如下-50:
| 策略 | 实现方式 | 优点 | 缺点 |
|---|---|---|---|
| URL 路径版本 | /v1/users、/v2/users | 直观可见,可缓存,易于测试 | 不够“纯粹 REST” |
| Header 版本 | Accept: application/vnd.api.v1+json | URL 简洁,符合 REST 理念 | 不够直观,调试不便 |
| 内容协商 | Accept: application/vnd.api+json;version=1 | 最符合 REST 原教旨 | 实现复杂 |
实践中,URL 路径版本控制是最实用的策略,被 Google、Microsoft、Stripe 等大厂广泛采用-50-。
4. 安全性设计
RESTful API 的安全保障需要从多个层面考虑:
传输安全:强制使用 HTTPS 加密通信
认证与授权:2026 年的主流方案是 OAuth 2.0 + JWT,API Key 适用于简单场景但安全性较弱-
输入校验:对所有客户端输入进行严格校验,防止注入攻击
CORS 策略:正确配置跨域资源共享策略,避免安全漏洞
限流与防刷:实施 API 限流策略,防止恶意请求和 DDoS 攻击
五、RESTful API vs GraphQL:对比分析
在 2026 年的 API 设计生态中,REST 和 GraphQL 是最主流的两种范式-34。了解二者的区别有助于技术选型。
| 维度 | REST | GraphQL |
|---|---|---|
| 数据获取方式 | 每个资源一个端点,可能多次请求 | 单次请求获取所需的所有数据 |
| 数据量控制 | 可能产生过获取或欠获取问题 | 客户端精确指定所需字段 |
| 缓存机制 | 天然支持 HTTP 缓存 | 需要额外实现缓存方案 |
| 学习曲线 | 低,基于 HTTP 标准 | 中等,需学习 Schema 和查询语法 |
| 适用场景 | CRUD 为主的公开 API、微服务间通信 | 复杂前端场景、多客户端需要不同数据形状 |
| 成熟度 | 极高,生态完善 | 较高,仍在快速发展 |
在 2026 年的工程实践中,REST 凭借成熟规范与广泛工具链支撑大规模分布式系统;GraphQL 则以精准数据获取与单请求多资源能力,显著优化前端交互效率。二者并非非此即彼,而是在不同场景下协同演进-34。
六、代码示例:从零实现一个 RESTful API
以下使用 Node.js + Express 实现一个简单的用户管理 RESTful API,并标注关键要点。
// app.js - RESTful API 完整示例 const express = require('express'); const app = express(); app.use(express.json()); // 解析 JSON 请求体 // 模拟数据库 let users = [ { id: 1, name: '张三', email: 'zhangsan@example.com' }, { id: 2, name: '李四', email: 'lisi@example.com' } ]; // ✅ GET /api/users - 获取所有用户(支持分页和过滤) app.get('/api/users', (req, res) => { const { page = 1, limit = 10 } = req.query; const start = (page - 1) limit; const result = users.slice(start, start + Number(limit)); res.status(200).json({ data: result, pagination: { page: Number(page), limit: Number(limit), total: users.length } }); }); // ✅ GET /api/users/:id - 获取单个用户 app.get('/api/users/:id', (req, res) => { const user = users.find(u => u.id === parseInt(req.params.id)); if (!user) { return res.status(404).json({ error: 'User not found' }); // 使用 404 状态码 } res.status(200).json(user); }); // ✅ POST /api/users - 创建新用户 app.post('/api/users', (req, res) => { const { name, email } = req.body; if (!name || !email) { return res.status(400).json({ error: 'Name and email are required' }); // 使用 400 } const newUser = { id: users.length + 1, name, email }; users.push(newUser); res.status(201).json(newUser); // ⭐ 创建成功使用 201 Created }); // ✅ PUT /api/users/:id - 全量更新用户 app.put('/api/users/:id', (req, res) => { const id = parseInt(req.params.id); const index = users.findIndex(u => u.id === id); if (index === -1) { return res.status(404).json({ error: 'User not found' }); } const { name, email } = req.body; users[index] = { id, name, email }; res.status(200).json(users[index]); }); // ✅ PATCH /api/users/:id - 局部更新用户 app.patch('/api/users/:id', (req, res) => { const id = parseInt(req.params.id); const user = users.find(u => u.id === id); if (!user) { return res.status(404).json({ error: 'User not found' }); } // 仅更新请求中提供的字段 if (req.body.name !== undefined) user.name = req.body.name; if (req.body.email !== undefined) user.email = req.body.email; res.status(200).json(user); }); // ✅ DELETE /api/users/:id - 删除用户 app.delete('/api/users/:id', (req, res) => { const id = parseInt(req.params.id); const index = users.findIndex(u => u.id === id); if (index === -1) { return res.status(404).json({ error: 'User not found' }); } users.splice(index, 1); res.status(204).send(); // ⭐ 删除成功使用 204 No Content });
执行流程说明:
客户端发送
GET /api/users请求服务器路由匹配到
/api/users,执行对应处理函数处理函数从
req.query中提取分页参数执行数据查询并构建响应体
设置状态码为 200,返回 JSON 格式的响应数据
七、底层原理支撑
RESTful API 之所以能够在现代 Web 架构中发挥巨大作用,底层依赖以下关键技术支撑:
HTTP 协议:REST 充分利用 HTTP 的请求方法、状态码、Header 等语义,HTTP 是 RESTful API 最主流的传输协议
URI 解析机制:Web 服务器和框架的 URI 路由解析能力是实现资源标识的基础
中间件/拦截器机制:用于实现认证、日志、限流等横切关注点
序列化/反序列化:JSON、XML 等数据格式的序列化能力
缓存机制:HTTP 缓存 Header 和 CDN 等基础设施支撑 REST 的可缓存特性
更深入的原理内容(如 Spring MVC 的请求处理流程、JAX-RS 的注解解析机制等)将在后续进阶专题中展开讲解。
八、高频面试题与参考答案
面试题一:什么是 REST?REST 的六大核心约束是什么?
参考答案:
REST(Representational State Transfer,表现层状态转移)是 Roy Fielding 在 2000 年提出的软件架构风格,不是协议也不是标准。REST 定义了六大核心约束:
统一接口:通过标准 HTTP 方法和 URI 实现统一的资源访问方式
无状态:服务器不保存客户端上下文,每个请求自包含
客户端-服务器分离:UI 与数据存储分离,可独立演进
可缓存:响应明确声明缓存策略,提升性能
分层系统:可加入中间层而不影响客户端
按需代码(可选) :服务器可返回可执行代码
踩分点:答出 REST 全称(Representational State Transfer)和提出者(Roy Fielding)加 2 分;六条约束每条 1 分,答对 4 条以上即可。
面试题二:RESTful API 中 URI 设计有哪些规范?为什么不能用动词?
参考答案:
URI 设计规范主要包括:
使用名词而非动词:URI 只标识资源,动作由 HTTP 方法表达(如
GET /users而非/getUsers)使用复数名词表示集合:如
/users而非/user层级表达从属关系:如
/users/123/orders统一使用小写和连字符:如
/user-profiles正确区分路径参数和查询参数:路径参数用于标识资源,查询参数用于过滤、排序和分页
不能用动词的原因:HTTP 方法已经表达了操作意图(GET 获取、POST 创建、PUT 更新、DELETE 删除),在 URI 中重复表达动词是冗余且混乱的,违背了 REST 的统一接口原则。
面试题三:RESTful API 中如何正确处理状态码?常见的误区有哪些?
参考答案:
状态码应严格遵循 HTTP 语义分层:
2xx 成功类:200 OK、201 Created、204 No Content
4xx 客户端错误:400 Bad Request、401 Unauthorized、403 Forbidden、404 Not Found、422 Unprocessable Entity
5xx 服务端错误:500 Internal Server Error、502 Bad Gateway、503 Service Unavailable
常见误区:
无论成功失败都返回 200,前端通过业务码判断——破坏了 HTTP 状态码的语义,增加开发和调试难度
POST 创建成功后返回 200 而非 201——未正确表达“资源已创建”的语义
DELETE 成功后返回 200 或空响应体——应返回 204 No Content
业务逻辑校验失败返回 400 而不是更精确的 422——422 更适合表达语义校验失败
面试题四:REST 和 GraphQL 的主要区别是什么?什么场景下选择 REST?
参考答案:
| 维度 | REST | GraphQL |
|---|---|---|
| 数据获取 | 多端点,可能多次请求 | 单请求,客户端指定所需字段 |
| 缓存 | 天然支持 HTTP 缓存 | 需额外实现 |
| 数据量 | 可能过获取或欠获取 | 精确获取 |
| 复杂度 | 低 | 中等 |
选择 REST 的场景:
CRUD 为主的公开 API,对数据形状要求稳定
需要充分利用 HTTP 缓存机制提升性能
团队规模大、技术栈多样,需要最广泛的支持和最低的学习成本
微服务间通信,需要简单、可调试的接口
API 需要被 AI Agent 自动发现和使用,REST 的规范性更适配-34
面试题五:RESTful API 如何实现版本管理?
参考答案:
主流版本管理策略有三种:
URL 路径版本:
/v1/users、/v2/users——最实用,直观可见,可缓存,易于测试,适合大多数团队Header 版本:通过自定义 Header(如
X-API-Version)传递版本信息——URL 更简洁,但不够直观内容协商:通过
AcceptHeader 中的媒体类型区分版本——最符合 REST 理念,但实现最复杂
实践建议:URL 路径版本控制是大多数团队的首选策略,同时需要配合弃用策略(Deprecation Header)和文档说明,确保客户端平滑迁移。
九、结尾总结
本文围绕 RESTful API 这一后端开发的核心知识点,从以下几个方面进行了系统梳理:
| 模块 | 核心要点 |
|---|---|
| ✅ 痛点分析 | 传统接口设计的命名混乱、方法滥用、状态码误用等问题 |
| ✅ 六大原则 | 统一接口、无状态、客户端-服务器分离、可缓存、分层系统、按需代码 |
| ✅ URI 设计 | 名词复数、小写连字符、路径参数 vs 查询参数、层级 ≤ 3 层 |
| ✅ HTTP 方法 | GET 查、POST 增、PUT 全改、PATCH 局部改、DELETE 删 |
| ✅ 状态码 | 2xx 成功、4xx 客户端错、5xx 服务端错,严禁 200 藏错误 |
| ✅ 版本管理 | URL 路径版本最实用,Header 更纯粹,内容协商最符合规范 |
| ✅ REST vs GraphQL | 数据获取方式、缓存机制、适用场景的核心差异 |
重点提醒:
记住 REST 的全称(Representational State Transfer)和提出者(Roy Fielding),面试中这是基础分
牢牢掌握 六大约束,尤其是无状态和统一接口,这是区分“真 RESTful”和“HTTP RPC”的关键
设计 API 时始终以 资源 为第一思考单位,而非动作
正确处理 状态码,这是专业素养的体现,也是面试中的高频考点
RESTful API 是后端开发的基础知识,但真正的理解需要结合实践不断深化。下一篇我们将深入讲解 RESTful API 的认证与授权机制(OAuth 2.0、JWT 实战),敬请期待。
本文由浩瀚ai助手整理自互联网公开技术资料,力求客观准确。如有信息偏差,欢迎指正。
