4、路径与操作:路径模板、HTTP方法映射、operationId、标签与分组、参数定义
路径与操作是OpenAPI契约的核心骨架。路径(Path)定义了API的端点地址,操作(Operation)则描述了在该端点上可执行的HTTP方法及其行为。本章将深入解析路径模板、HTTP方法映射、operationId、标签与分组以及参数定义这五个关键要素,帮助你在契约设计中建立清晰、可维护的边界。
4.1 路径模板:动态参数的占位符
路径模板允许在URL路径中使用花括号 {} 定义动态参数,使一个路径模板能够匹配多个实际请求。例如:
/users/{userId}/orders/{orderId}
路径模板中的参数必须在 parameters 字段中明确定义,并指定其位置为 path。路径参数是必需的,因为缺少它们会导致请求无法路由到正确的资源。
| 路径模板示例 | 匹配的请求示例 | 说明 |
|---|---|---|
/users/{userId} |
/users/12345 |
获取ID为12345的用户 |
/items/{itemId}/reviews |
/items/abc-xyz/reviews |
获取特定商品的所有评论 |
/reports/{year}/{month} |
/reports/2025/04 |
获取2025年4月的报告 |
userId 而非 id),并在描述中说明其格式或取值范围,以提升契约的可读性。
4.2 HTTP方法映射:操作与语义的绑定
每个路径下可以定义多个HTTP方法,每个方法对应一个操作。OpenAPI 3.0支持的方法包括:get、post、put、patch、delete、head、options 和 trace。方法的选择应严格遵循HTTP语义:
- GET:检索资源,不应有副作用。
- POST:创建资源或触发处理。
- PUT:完全替换资源。
- PATCH:部分更新资源。
- DELETE:移除资源。
错误的HTTP方法映射会导致API语义混乱。例如,使用GET方法删除资源或使用POST方法查询只读数据,都会破坏契约的领域边界。
paths:
/users/{userId}:
get:
summary: 获取用户信息
operationId: getUserById
put:
summary: 更新用户信息(全量替换)
operationId: updateUser
delete:
summary: 删除用户
operationId: deleteUser
4.3 operationId:操作的唯一标识符
operationId 是每个操作的唯一字符串标识符,在整个API文档中必须唯一。它通常用于生成客户端SDK的方法名、日志追踪以及API文档的锚点链接。
getUserById、createOrder、deleteItem。避免使用空格、连字符或特殊字符。
如果未显式指定 operationId,工具可能会自动生成,但自动生成的名称往往缺乏可读性。显式定义 operationId 是契约设计中的一项重要纪律。
paths:
/orders:
get:
operationId: listOrders
summary: 获取订单列表
post:
operationId: createOrder
summary: 创建新订单
4.4 标签与分组:组织操作的逻辑边界
标签(Tags)用于对操作进行逻辑分组,在API文档中形成清晰的导航结构。一个操作可以关联多个标签,但通常建议每个操作只关联一个主要标签,以保持分组简洁。
标签可以在全局 tags 字段中预先定义并添加描述,也可以在操作中直接使用字符串。推荐在全局定义标签,以便统一管理。
tags:
- name: Users
description: 用户管理相关操作
- name: Orders
description: 订单管理相关操作
- name: Payments
description: 支付处理相关操作
paths:
/users:
get:
tags: [Users]
operationId: listUsers
post:
tags: [Users]
operationId: createUser
/orders:
get:
tags: [Orders]
operationId: listOrders
post:
tags: [Orders]
operationId: createOrder
Payments 标签可以统一呈现。
4.5 参数定义:位置、类型与约束
参数可以在路径、查询字符串、请求头、Cookie等位置传递。每个参数必须明确定义其名称、位置(in)、类型(schema)以及是否必需(required)。
| 参数位置(in) | 说明 | 示例 |
|---|---|---|
path |
URL路径中的动态部分 | /users/{userId} |
query |
URL问号后的键值对 | ?page=1&limit=10 |
header |
HTTP请求头 | X-Request-Id |
cookie |
HTTP Cookie | sessionId |
参数定义示例:
parameters:
- name: userId
in: path
required: true
description: 用户的唯一标识符
schema:
type: string
format: uuid
- name: page
in: query
required: false
description: 分页页码,从1开始
schema:
type: integer
minimum: 1
default: 1
- name: X-Request-Id
in: header
required: false
description: 用于请求追踪的唯一ID
schema:
type: string
4.6 路径与操作的整体结构
以下SVG图展示了路径、操作、参数、标签与operationId之间的层级关系,帮助你理解它们在契约中的组织方式。
4.7 参数复用与路径级参数
当多个操作共享相同的参数时,可以将参数定义在路径级别(parameters 字段直接放在路径对象下),而不是在每个操作中重复定义。路径级参数会被该路径下的所有操作继承,但操作级参数可以覆盖路径级参数的同名定义。
paths:
/users/{userId}:
parameters:
- name: userId
in: path
required: true
schema:
type: string
get:
operationId: getUserById
# 继承路径级参数 userId
put:
operationId: updateUser
# 继承路径级参数 userId
parameters:
- name: X-Idempotency-Key
in: header
required: true
schema:
type: string
4.8 参数约束与校验
OpenAPI支持在参数定义中设置丰富的约束条件,帮助API消费者提前了解输入限制,减少无效请求。
| 约束字段 | 适用类型 | 说明 |
|---|---|---|
minimum / maximum |
number, integer | 数值范围限制 |
minLength / maxLength |
string | 字符串长度限制 |
pattern |
string | 正则表达式模式 |
enum |
任意类型 | 枚举允许值列表 |
minItems / maxItems |
array | 数组元素数量限制 |
合理使用约束条件,可以在契约层面实现“防御性设计”,将校验逻辑前置到API网关或客户端SDK中,降低后端服务的无效负载。
parameters:
- name: status
in: query
required: false
description: 订单状态筛选
schema:
type: string
enum: [pending, confirmed, shipped, delivered, cancelled]
- name: email
in: query
required: false
schema:
type: string
pattern: '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
通过路径模板、HTTP方法映射、operationId、标签与分组以及参数定义这五个维度的精确设计,你能够构建出结构清晰、语义明确、易于扩展的OpenAPI契约。这些要素共同构成了API的“领域边界”,让契约成为前后端、微服务之间可靠的通信协议。