**RESTful API(Representational State Transfer,表现层状态转移)是一种基于 HTTP 协议设计 API 的规范,核心是通过 **资源(Resource) 为中心,利用 HTTP 方法和状态码实现无状态、可扩展的接口交互。其规范并非强制标准,但遵循统一规则能大幅提升 API 的可读性、可维护性和兼容性。以下是 RESTful API 的核心使用规范,按「资源设计」「HTTP 方法使用」「URL 命名」「状态码」「请求 / 响应格式」等维度详细说明:
一、核心原则:以「资源」为中心
**RESTful 的核心是「资源」(如用户、订单、商品),而非「操作」(如获取用户、删除订单)。API 设计需围绕资源的「CRUD(创建、读取、更新、删除)」操作展开,避免在 URL 中包含动词(如 **getUser、deleteOrder)。
反例(URL 含动词,不符合资源中心):
GET /getUser?id=123POST /deleteOrder/456
正例(URL 仅描述资源,操作通过 HTTP 方法体现):
GET /users/123(读取用户)DELETE /orders/456(删除订单)
二、URL 命名规范:简洁、语义化、小写
URL 是资源的唯一标识,需遵循以下规则:
- 使用名词复数表示资源集合 **资源集合(如所有用户、所有订单)用复数名词,单个资源用「集合 + ID」表示,避免单数(如 **
/user)导致歧义。- 集合:
/users(所有用户)、/orders(所有订单)、/products(所有商品) - 单个资源:
/users/123(ID 为 123 的用户)、/orders/456(ID 为 456 的订单)
- 集合:
- 层级关系用嵌套 URL 表示(避免过深) 若资源存在从属关系(如「用户的订单」),可用嵌套 URL 体现,但嵌套层级建议不超过 2 层(过深会导致 URL 冗长、维护复杂)。
- 正例:
/users/123/orders(用户 123 的所有订单)、/users/123/orders/456(用户 123 的订单 456) - 反例(过深):
/users/123/orders/456/products/789(建议拆分为/orders/456/products/789)
- 正例:
- 统一小写 + 分隔符用「连字符(-)」 **URL 区分大小写(如 **
/Users和/users是两个不同地址),因此统一用小写;若资源名由多个单词组成,用连字符-分隔(避免下划线_或驼峰式camelCase)。- 正例:
/user-profiles(用户资料)、/product-categories(商品分类) - 反例:
/userProfiles、/product_categories
- 正例:
三、HTTP 方法:映射资源的 CRUD 操作
**HTTP 协议提供了 8 种方法,RESTful API 仅使用其中 5 种核心方法,严格对应资源的 CRUD 操作,避免 “方法滥用”(如用 **GET 做删除)。
| HTTP 方法 | 对应操作 | 作用说明 | 幂等性? | 安全性? |
|---|---|---|---|---|
GET |
读取(Read) | 获取资源(单个 / 集合),不修改服务器数据 | 是 | 是 |
POST |
创建(Create) | 新增资源(如新建用户、提交订单) | 否 | 否 |
PUT |
全量更新(Update) | 覆盖更新资源的所有字段(需传完整资源数据) | 是 | 否 |
PATCH |
部分更新(Update) | 仅更新资源的部分字段(无需传完整数据) | 是 | 否 |
DELETE |
删除(Delete) | 删除指定资源 | 是 | 否 |
关键概念解释:
- 幂等性:多次调用同一接口,结果一致(不会因调用次数导致副作用)。例如
GET /users/123调用 10 次,结果相同;DELETE /users/123调用多次,第一次删除后,后续调用返回 “资源不存在”,仍符合幂等性。 - 安全性:调用接口不会修改服务器数据(仅
GET满足,POST/PUT/PATCH/DELETE均会修改数据,因此不安全)。
常见错误用法:
- **用 **
GET传递敏感数据(如GET /users?username=admin&password=123):GET请求参数会暴露在 URL 中,存在安全风险,应改用POST并将数据放在请求体。 - **用 **
POST做更新 / 删除(如POST /users/123/delete):应改用PUT/PATCH(更新)或DELETE(删除),遵循方法语义。
四、HTTP 状态码:明确返回请求结果
**RESTful API 需使用标准 HTTP 状态码,避免自定义状态码(如返回 **{code: 200, msg: "成功"} 中的 code 可省略,直接用 HTTP 状态码),让客户端快速识别请求结果。
核心状态码分类及使用场景:
| 状态码范围 | 类别 | 常用状态码 | 说明场景 |
|---|---|---|---|
| 2xx | 成功 | 200 | 请求成功(如GET读取资源、PUT更新成功) |
| 201 | 资源创建成功(仅POST新增资源时返回) |
||
| 204 | 请求成功但无返回数据(如DELETE删除后) |
||
| 4xx | 客户端错误 | 400 | 请求参数错误(如必填字段缺失、格式错误) |
| 401 | 未授权(需登录但未携带 Token / 密码错误) | ||
| 403 | 权限不足(已登录但无操作权限,如普通用户删管理员) | ||
| 404 | 资源不存在(如GET /users/999,ID 999 不存在) |
||
| 405 | 方法不允许(如用POST访问GET接口) |
||
| 5xx | 服务器错误 | 500 | 服务器内部错误(如代码 bug、数据库异常) |
| 503 | 服务不可用(如服务器维护、过载) |
示例:
- **客户端请求 **
DELETE /users/123,若用户存在且删除成功,返回204 No Content; - **若用户不存在,返回 **
404 Not Found; - **若客户端未登录,返回 **
401 Unauthorized。
五、请求 / 响应格式:统一、清晰、兼容
1. 数据格式:优先用 JSON
**RESTful API 建议统一使用 **JSON 作为数据交换格式(避免 XML、FormData 等混合使用),请求头需指定 Content-Type: application/json,响应头同样返回 Content-Type: application/json。
请求体示例(POST 新增用户):
// POST /users
{
"username": "zhangsan",
"email": "zhangsan@example.com",
"age": 25
}
响应体示例(GET 单个用户):
// GET /users/123 -> 状态码 200 OK
{
"code": 0, // 可选(补充业务状态,如 0=成功,1001=用户名已存在)
"message": "success",
"data": {
"id": 123,
"username": "zhangsan",
"email": "zhangsan@example.com",
"age": 25,
"created_at": "2024-05-01T10:30:00Z" // 时间用 ISO8601 格式(如 UTC 时间)
}
}
2. 响应体结构:统一包裹
**即使无数据返回,也建议用统一结构包裹(如 **{code: 0, message: "success", data: {}}),避免客户端处理不同格式的响应(如有时返回对象、有时返回数组)。
3. 分页、过滤、排序:用查询参数(Query Param)
**对资源集合(如 **/users)的分页、过滤、排序操作,通过 URL 查询参数实现,不修改 URL 路径。
| 需求 | 查询参数示例 | 说明 |
|---|---|---|
| 分页 | /users?page=2&size=10 |
第 2 页,每页 10 条数据 |
| 过滤 | /users?age=25&gender=male |
筛选年龄 25、性别男的用户 |
| 排序 | /users?sort=created_at,desc |
按创建时间降序排列(asc = 升序,desc = 降序) |
| 字段筛选 | /users?fields=id,username,email |
仅返回 id、username、email 字段 |
六、其他关键规范
1. 无状态设计
**RESTful API 必须是 **无状态 的:服务器不存储客户端的会话信息(如登录状态),客户端每次请求需携带完整的身份凭证(如 Token、JWT),确保请求可独立处理(便于服务器水平扩展)。
2. 版本控制
API 迭代时需做版本控制,避免旧版本客户端报错。常用两种方式:
- URL 路径包含版本(推荐,直观):
/v1/users、/v2/users - 请求头包含版本:
Accept: application/json;version=1.0
3. 避免跨域问题
若 API 供前端页面调用(如浏览器端),需配置 CORS(跨域资源共享),在响应头中添加:
Access-Control-Allow-Origin: * // 允许所有域名(生产环境建议指定具体域名,如 https://example.com)
Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization // 允许携带的请求头(如 Token 放在 Authorization 中)
4. 错误信息明确
客户端请求失败时(如 400、401),响应体需返回具体错误原因,便于调试,避免仅返回状态码。
错误响应示例(400 Bad Request):
{
"code": 1002,
"message": "请求参数错误",
"errors": [
{
"field": "email",
"message": "邮箱格式不正确(需符合 xxx@xxx.com)"
},
{
"field": "age",
"message": "年龄必须大于 0"
}
]
}
七、规范落地示例(完整 API 清单)
以「用户(User)」资源为例,符合 RESTful 规范的 API 设计如下:
| HTTP 方法 | URL | 功能描述 | 状态码(成功) | 请求体(关键参数) | 响应体(关键数据) |
|---|---|---|---|---|---|
GET |
/v1/users |
获取用户列表(支持分页) | 200 | -(分页参数在 Query:page/size) | data: [{id, username, ...}] |
GET |
/v1/users/123 |
获取单个用户详情 | 200 | - | data: {id, username, email, ...} |
POST |
/v1/users |
新增用户 | 201 | username, email, age |
data: {id, username, ...} |
PUT |
/v1/users/123 |
全量更新用户(需传所有字段) | 200 | username, email, age, ... |
data: {id, username, ...} |
PATCH |
/v1/users/123 |
部分更新用户(仅传修改字段) | 200 | email(仅修改邮箱) |
data: {id, username, ...} |
DELETE |
/v1/users/123 |
删除用户 | 204 | - | 无数据(仅返回状态码) |
总结
**RESTful API 的核心是「**资源为中心 + HTTP 语义化」,遵循规范的目的是让 API 具备「自描述性」—— 即使不看文档,开发者也能通过 URL 和 HTTP 方法快速理解接口功能。实际落地时,需结合业务场景灵活调整(如复杂查询可适当放宽 URL 嵌套限制),但核心原则(如 URL 无动词、HTTP 方法对应操作、状态码准确)需严格遵守。
评论区 1