一文掌握 RESTful API 设计规范与实战技巧

在微服务架构中,API 是服务间通信和前后端交互的核心。RESTful API 作为一种基于 HTTP 协议的设计规范,通过 “资源为中心” 的思想和语义化的操作,让接口具备一致性、可读性和可扩展性。本文结合实战场景,详细讲解 RESTful API 的设计规范,包含 URI 命名、HTTP 方法使用、状态码、响应格式等关键内容,并融入具体示例帮助理解。

一、RESTful API 核心原则

RESTful API 的设计围绕以下核心原则展开,这些原则是规范的基础:

  1. 以资源为中心
    所有接口设计都围绕 “资源”(如用户、商品、订单)展开,资源通过 URI(统一资源标识符)唯一标识,而非围绕 “操作”(如 “获取用户”“删除订单”)。

  2. HTTP 方法语义化
    利用 HTTP 的方法(GET、POST、PUT、PATCH、DELETE)表达对资源的操作,而非在 URI 中使用动词(如/getUser/deleteOrder)。

  3. 无状态通信
    服务器不存储客户端状态,每次请求必须包含所有必要信息(如 Token、参数),便于服务水平扩展。

  4. 统一接口
    接口格式、响应结构、状态码使用保持一致,降低开发者学习和使用成本。

二、URI 设计规范:资源的唯一标识

URI(Uniform Resource Identifier)是资源的唯一地址,其设计直接影响 API 的可读性和一致性。

1. 基础规则

  • 使用小写字母:避免大小写混合(如/Api/V1/Users是错误的),统一小写(/api/v1/users)。
  • 连字符(-)分隔多单词:如/order-details(订单详情),不使用下划线(_)或驼峰(orderDetails)。
  • 不包含动词:URI 中只体现资源,操作通过 HTTP 方法表达(如/users而非/getUsers)。
  • 版本控制:在 URI 中包含版本(如/api/v1/users),便于迭代升级(后续可扩展v2版本,不影响旧版本)。

2. 资源路径设计

(1)资源集合与单个资源
  • 资源集合用复数名词表示:/api/v1/users(用户列表)、/api/v1/goods(商品列表)。
  • 单个资源用 “集合 + ID” 表示:/api/v1/users/1(ID 为 1 的用户)、/api/v1/goods/1001(ID 为 1001 的商品)。
资源描述
/users所有用户(集合)
/users/1ID 为 1 的单个用户
/goods所有商品(集合)
/goods/1001ID 为 1001 的单个商品
(2)资源间关系:体现嵌套层级

当资源存在从属关系时,用子路径表示。例如:

  • GET /api/v1/users/1/orders:用户 1 的所有订单(订单从属于用户)。
  • GET /api/v1/orders/10/items:订单 10 包含的所有商品条目(条目从属于订单)。

注意:避免过深嵌套(如/users/1/orders/10/items/5),可通过查询参数简化。例如,查询订单 10 的条目 5,可设计为/api/v1/order-items/5?orderId=10

(3)反例与正例对比
不规范 URI问题说明规范 URI
/api/getUser?id=1URI 包含动词get/api/v1/users/1
/api/user/delete/1URI 包含动词delete/api/v1/users/1(用 DELETE 方法)
/Api/V1/Users/1大小写混合/api/v1/users/1
/api/v1/user_orders/1使用下划线分隔/api/v1/user-orders/1
/api/v1/users/1/orders/10/items嵌套过深/api/v1/order-items?orderId=10

 

三、HTTP 方法与资源操作的对应关系

RESTful API 通过 HTTP 方法表达对资源的操作,每种方法有明确的语义和适用场景:

HTTP 方法操作类型幂等性 *适用场景示例 URI示例描述
GET查询资源获取资源列表或单个资源/api/v1/users查询所有用户
/api/v1/users/1查询 ID 为 1 的用户
POST创建资源新建资源(服务器生成 ID)/api/v1/users创建新用户
PUT全量更新资源替换资源的所有字段(需提供完整资源信息)/api/v1/users/1完整更新用户 1 的信息(如替换所有字段)
PATCH部分更新资源仅更新资源的部分字段/api/v1/users/1更新用户 1 的昵称(其他字段不变)
DELETE删除资源删除指定资源/api/v1/users/1删除 ID 为 1 的用户

* 幂等性:多次执行相同操作,结果一致(如 GET 多次查询结果相同,PUT 多次更新结果相同;POST 创建资源多次会生成多个记录,因此非幂等)。 

实战示例:用户资源的完整接口

# 1. 查询用户列表
GET /api/v1/users

# 2. 查询单个用户
GET /api/v1/users/1

# 3. 创建用户(服务器生成ID)
POST /api/v1/users

# 4. 全量更新用户(需传递所有必填字段)
PUT /api/v1/users/1

# 5. 部分更新用户(仅传递需修改的字段)
PATCH /api/v1/users/1

# 6. 删除用户
DELETE /api/v1/users/1

如何区分 GET 和 POST? 

GET 请求
🔹 适用场景:
  • 获取列表(如购物车列表)
  • 查询单个资源
  • 过滤、排序、分页等操作
POST 请求
🔹 适用场景:
  • 创建新资源(如添加购物车条目)
  • 提交用户输入的数据
  • 操作会引起服务端状态变化
判断标准使用 GET使用 POST
是否要修改服务器状态?❌ 不会修改✅ 会修改
是否要上传大量/敏感数据?❌ 不适合✅ 推荐
是否需要幂等性?✅ 需要❌ 不需要
是否是“读取”操作?✅ 是❌ 否
是否是“创建”操作?❌ 否✅ 是

总结一句话:

如果你是在获取数据且不修改服务器状态 → 用 GET;<br>如果你是在创建、更新或删除资源 → 用 POST / PUT / DELETE

这样设计出的接口才符合 RESTful 规范,也更容易维护和理解。

 

四、请求体设计规范

请求体(Request Body)用于传递资源的创建、更新信息,推荐使用JSON 格式,并遵循以下规范:

1. 字段命名与格式

  • 统一命名风格:选择驼峰命名(camelCase)或蛇形命名(snake_case),并保持全局一致(推荐蛇形命名,更符合数据库字段风格)。
  • 避免冗余字段:不传递与资源无关的信息(如无需在创建用户时传递update_time,由服务器生成)。
  • 嵌套结构清晰:复杂资源可使用嵌套 JSON(如用户的地址信息)。

2. 实战示例

(1)创建用户(POST /api/v1/users)
{
  "username": "zhangsan",
  "email": "zhangsan@example.com",
  "age": 25,
  "address": {  // 嵌套结构
    "province": "beijing",
    "city": "beijing"
  }
}
(2)部分更新用户(PATCH /api/v1/users/1)
{
  "age": 26,  // 仅更新年龄字段
  "email": "new-zhangsan@example.com"  // 同时更新邮箱
}

 

五、响应体设计规范

响应体(Response Body)需统一格式,包含状态标识、数据、错误信息(按需返回),便于客户端解析。

1. 通用结构

响应体应包含以下核心字段(JSON 格式):

字段名类型说明出现场景
code整数业务状态码(通常与 HTTP 状态码一致)所有响应
message字符串操作结果描述(如 “成功”“参数错误”)所有响应
data任意业务数据(查询 / 创建 / 更新的资源信息)成功响应(2xx)
error字符串错误详情(如参数校验失败的具体原因)失败响应(4xx/5xx)
timestamp整数响应时间戳(毫秒)可选,便于问题排查

2. 成功响应示例

(1)查询单个资源(GET /api/v1/users/1)
{
  "code": 200,
  "message": "success",
  "timestamp": 1690000000000,
  "data": {
    "id": 1,
    "username": "zhangsan",
    "email": "zhangsan@example.com",
    "age": 25,
    "created_at": "2023-01-01T00:00:00Z"
  }
}
(2)创建资源(POST /api/v1/users)
{
  "code": 201,  // 对应HTTP状态码201(创建成功)
  "message": "created",
  "timestamp": 1690000001000,
  "data": {
    "id": 2,  // 服务器生成的新资源ID
    "username": "lisi",
    "created_at": "2023-08-01T00:00:00Z"
  }
}
(3)删除资源(DELETE /api/v1/users/1)
{
  "code": 204,  // 对应HTTP状态码204(无内容)
  "message": "deleted",
  "timestamp": 1690000002000
  // 无data字段(删除成功无需返回资源)
}

3. 失败响应示例

(1)参数错误(400 Bad Request)
{
  "code": 400,
  "message": "参数错误",
  "timestamp": 1690000003000,
  "error": "email格式不正确(应为xxx@xx.com)"
}
(2)资源不存在(404 Not Found)
{
  "code": 404,
  "message": "资源不存在",
  "timestamp": 1690000004000,
  "error": "用户ID=999不存在"
}
(3)服务器内部错误(500 Internal Server Error)
{
  "code": 500,
  "message": "服务器内部错误",
  "timestamp": 1690000005000,
  "error": "数据库连接超时"  // 生产环境可简化为“系统繁忙,请稍后再试”
}

 

六、HTTP 状态码的正确使用

HTTP 状态码是 RESTful API 的 “语言”,客户端可通过状态码快速判断请求结果,无需解析响应体。以下是常用状态码及适用场景:

1. 2xx(成功)

状态码含义适用场景
200OK(成功)GET 查询成功、PUT/PATCH 更新成功
201Created(创建成功)POST 创建资源成功(如新建用户、订单)
204No Content(无内容)DELETE 删除成功、无需返回数据的 PUT 请求

2. 4xx(客户端错误)

状态码含义适用场景
400Bad Request(请求错误)参数格式错误(如手机号位数不正确)
401Unauthorized(未认证)未携带 Token、Token 无效或过期
403Forbidden(权限不足)已认证但无操作权限(如普通用户删除管理员)
404Not Found(资源不存在)请求 URI 错误(如/api/v1/usrs)或资源 ID 不存在
405Method Not Allowed请求方法不支持(如对/users/1用 POST)
409Conflict(资源冲突)创建用户时用户名已存在、修改资源版本冲突
422Unprocessable Entity参数校验失败(如年龄为负数)

3. 5xx(服务器错误)

状态码含义适用场景
500Internal Server Error服务器内部错误(如代码 Bug、数据库连接失败)
503Service Unavailable服务不可用(如过载、维护中)

注意事项

  • 状态码与业务一致:如 “资源不存在” 必须返回 404,而非 200 + 错误消息(客户端可能依赖状态码处理逻辑)。
  • 避免滥用 500:500 应仅用于服务器未预期的错误,客户端可修复的错误(如参数错误)应返回 4xx。

七、分页、排序与过滤的设计

对于资源列表查询(如GET /api/v1/users),需支持分页、排序、过滤功能,通过查询参数(Query Parameters) 实现。

1. 分页参数

参数名含义示例
page当前页码(从 1 开始)?page=1(第一页)
size每页条数?page=1&size=10(每页 10 条,第一页)

响应示例(GET /api/v1/users?page=1&size=2):

{
  "code": 200,
  "message": "success",
  "data": {
    "items": [  // 当前页数据
      {"id": 1, "username": "zhangsan"},
      {"id": 2, "username": "lisi"}
    ],
    "total": 100,  // 总条数
    "page": 1,     // 当前页
    "size": 2,     // 每页条数
    "pages": 50    // 总页数
  }
}

2. 排序参数

参数名含义示例
sort排序字段及方向(字段,方向?sort=age,asc(按年龄升序)
?sort=create_time,desc(按创建时间降序)

3. 过滤参数

根据资源字段定义过滤条件,常用方式:

过滤类型参数示例含义
等值过滤?status=active查询状态为 “active” 的用户
范围过滤?age_min=18&age_max=30查询年龄 18-30 的用户
模糊搜索?username_like=zhang查询用户名包含 “zhang” 的用户
多值过滤?ids=1,2,3查询 ID 为 1、2、3 的用户

综合示例

查询 “第 2 页、每页 10 条、按创建时间降序、状态为 active 的用户”:

GET /api/v1/users?page=2&size=10&sort=create_time,desc&status=active

 

八、版本控制策略

API 迭代过程中,需保证旧版本兼容性,常用的版本控制方式有以下 3 种:

1. URI 路径包含版本(推荐)

在 URI 中显式包含版本号(如v1v2),清晰直观,便于测试和维护:

/api/v1/users  // 版本1
/api/v2/users  // 版本2(不影响v1的使用)

2. 请求头包含版本

通过Accept请求头指定版本,不污染 URI,但客户端实现稍复杂:

Accept: application/vnd.example.v1+json  // 调用v1版本
Accept: application/vnd.example.v2+json  // 调用v2版本

3. 查询参数包含版本

通过version参数指定版本,不推荐(易被忽略,且不符合 “资源唯一 URI” 原则):

/api/users?version=1  // 不推荐

 

九、实战:完整的商品 API 设计示例

以电商系统的 “商品” 资源为例,展示符合 RESTful 规范的完整 API 设计:

方法URI功能描述请求体示例响应体示例(成功)
GET/api/v1/goods查询商品列表-{"code":200,"message":"success","data":{"items":[...],"total":100}}
GET/api/v1/goods/1001查询单个商品-{"code":200,"message":"success","data":{"id":1001,"name":"手机","price":3999}}
POST/api/v1/goods创建商品{"name":"电脑","price":5999,"stock":100}{"code":201,"message":"created","data":{"id":1002,"name":"电脑"}}
PUT/api/v1/goods/1001全量更新商品{"name":"手机(新款)","price":4999,"stock":50}{"code":200,"message":"success","data":{"id":1001,"name":"手机(新款)"}}
PATCH/api/v1/goods/1001部分更新商品{"stock":49}{"code":200,"message":"success","data":{"id":1001,"stock":49}}
DELETE/api/v1/goods/1001删除商品-{"code":204,"message":"deleted"}

 

十、总结

RESTful API 设计规范的核心是 “一致性”—— 统一的 URI 命名、HTTP 方法使用、响应格式和状态码,让接口易于理解和使用。在微服务项目中,遵循这些规范能带来以下好处:

  • 降低沟通成本:团队成员无需额外文档即可理解接口功能。
  • 便于扩展:规范的设计让 API 迭代(如新增字段、版本升级)更平滑。
  • 跨团队协作:前端、后端、第三方开发者遵循同一标准,减少适配成本。

实际开发中,可结合框架(如 Spring Boot 的@RestController、FastAPI)自动生成符合规范的接口,并通过 Swagger 等工具生成 API 文档,进一步提升开发效率。

如果这篇文章对大家有帮助可以点赞关注,你的支持就是我的动力😊!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值