2026-08-21 14:47:46.324577+08 / restful-api
Resources
围绕业务资源建模、资源命名、层级设计和标识符设计的 RESTful API 指南。
Resources
对业务领域进行建模
API 应对业务领域进行建模,并暴露能够表达有意义业务概念的资源。
资源应包含 API 消费者所需的必要信息,同时避免暴露内部实现细节。
良好的资源模型可以带来:
- 对业务领域更清晰的理解
- 一致的资源表示方式
- 降低客户端与服务之间的耦合
- 更好的 API 演进能力
API 不应只是数据库表的简单包装。业务概念和领域逻辑应通过有意义的资源表达,而不是直接暴露持久化模型。
对于复杂领域,可以根据不同业务上下文使用不同模型。应始终清晰定义模型适用的上下文。
定义有用的资源
资源应覆盖大多数客户端使用场景。
有用的资源应:
- 为常见场景提供足够的信息
- 避免暴露不必要的数据
- 通过过滤、分页或嵌入机制提供灵活性
目标是提供平衡的资源表示:
- 信息太少,会迫使客户端发起不必要的 API 调用。
- 信息太多,会增加负载大小和耦合程度。
避免在资源 URL 中使用动作
REST API 应以资源为中心。
动作应通过 HTTP 方法表达,而不是在 URL 中使用动词。
使用:
POST /orders
GET /orders/{id}
PUT /orders/{id}
DELETE /orders/{id}
避免:
POST /orders/create
POST /orders/{id}/cancel
POST /orders/{id}/approve
URL 应表示资源,HTTP 方法应表示操作。
将动作建模为资源
当一个操作代表业务事件或状态转换时,可以将其建模为资源。
例如,不使用:
POST /vehicles/{vehicleId}/lock
可以使用:
PUT /vehicles/{vehicleId}/doors-lock
{
"lockStatus": "locked"
}
或者:
POST /vehicles/{vehicleId}/door-actions
{
"type": "unlock"
}
这种方式具有更好的扩展性,因为动作未来可以成为持久化资源,并支持:
- 时间戳
- 审计信息
- 历史记录查询
- 额外元数据
将复杂操作建模为资源
对于需要多个参数的复杂操作,应创建专用资源。
例如,不使用:
POST /vehicles/move
可以使用:
POST /vehicle-transfers
{
"sourceOrganizationId": "org-a",
"targetOrganizationId": "org-b",
"vehicles": [
"vehicle-1",
"vehicle-2"
]
}
这样会创建一个表示转移操作的资源,并支持:
- 跟踪操作状态
- 审计历史操作
- 支持异步处理
使用领域专属的资源名称
资源名称应表达业务概念。
推荐:
/sales-orders
/customers
/payment-transactions
避免使用泛化名称:
/items
/data
/entities
/objects
领域专属名称可以改善:
- API 可读性
- 开发者理解程度
- 文档质量
使用适合 URL 的资源标识符
URL 中使用的资源标识符应只包含 URL 安全字符。
推荐字符:
A-Z
a-z
0-9
-
_
:
.
应避免使用需要额外编码的标识符。
示例:
推荐:
/customers/customer_123
避免:
/customers/customer name with spaces
通过路径段标识资源和子资源
资源和子资源应通过 URL 路径段表示。
通用结构:
/resources/{resource-id}/sub-resources/{sub-resource-id}
示例:
/customers/123
/customers/123/addresses
/customers/123/addresses/home
有效的资源路径通常意味着父资源也存在。
例如:
/customers/123/addresses/home
应隐含以下资源路径:
/customers
/customers/123
/customers/123/addresses
复合标识符不应使用 / 作为分隔符。
只在必要时使用 UUID
在分布式系统中,如果标识符必须由多个系统独立生成,UUID 会很有用。
但是 UUID 也有以下缺点:
- 人类难以阅读和记忆
- 调试不够方便
- 存储和网络开销更大
- 没有自然顺序
- 不太适合作为面向用户的标识符
以下情况可以优先使用 UUID:
- 需要大规模分布式 ID 生成
- 多个系统需要独立生成 ID
- 避免标识符冲突非常重要
对于简单的业务实体,可以优先使用服务端生成的标识符。
无论使用哪种标识符:
- ID 都应表示为字符串
- ID 创建后应保持稳定
- ID 不应被重新分配给其他对象
限制资源类型数量
API 应避免暴露过多彼此无关的资源类型。
资源类型表示一组关系紧密的资源。
示例:
/customers
/customers/{id}
/customers/{id}/addresses
/addresses
设计良好的 API 通常只包含有限数量的资源类型。
如果 API 暴露了大量互不相关的资源,应考虑根据业务领域或限界上下文拆分 API。
限制子资源嵌套层级
只有当子资源的生命周期与父资源高度相关时,才应使用嵌套资源。
推荐:
/customers/{id}/orders/{orderId}
避免深层嵌套:
/customers/{id}/orders/{orderId}/items/{itemId}/details/{detailId}
深层嵌套会导致:
- URL 复杂
- API 不易发现
- 耦合增加
通常建议将嵌套深度限制在约三层以内。
总结
良好的 REST API 应:
- 对业务概念建模,而不是暴露数据库结构
- 在 URL 中使用名词,而不是动词
- 将复杂操作表示为资源
- 使用有意义的领域专属资源名称
- 保持标识符适合 URL 使用
- 只在需要时使用 UUID
- 避免资源类型过多
- 避免资源深层嵌套
目标是创建可预测、易理解、可扩展且易于客户端使用的 API。