3. 接口契约定义:OpenAPI/Swagger规范介绍、YAML/JSON语法基础、契约文件结构解析
接口契约是API治理的基石。在微服务架构中,服务提供者与服务消费者之间必须有一份双方共同遵守的“协议”,这份协议就是接口契约。它定义了请求的格式、响应的结构、参数约束、错误码以及认证方式。本章将深入解析业界最主流的契约规范——OpenAPI(原Swagger),并掌握其描述语言YAML/JSON的核心语法与文件结构。
3.1 OpenAPI/Swagger规范概述
OpenAPI规范(OAS)是一种用于描述HTTP API的标准化、语言无关的接口定义格式。它最初由Swagger项目贡献,现由Linux基金会旗下的OpenAPI Initiative维护。目前最广泛使用的版本是OpenAPI 3.0.x。
| 特性 | Swagger 2.0 | OpenAPI 3.0 |
|---|---|---|
| 核心对象 | Swagger Object | OpenAPI Object |
| 请求体描述 | body参数 + formData参数 | 独立的 requestBody 对象 |
| 响应描述 | responses 内联定义 | responses + 可复用的 components |
| 多内容类型 | 有限支持 | 原生支持 content 对象 |
| 回调/Webhook | 不支持 | 支持 callback 和 webhook |
| 安全方案 | securityDefinitions | components/securitySchemes |
3.2 YAML/JSON语法基础
OpenAPI契约文件支持YAML和JSON两种序列化格式。YAML因其可读性高、注释支持好,成为社区首选;JSON则更适合机器生成和传输场景。
3.2.1 YAML核心语法
- 缩进:使用空格(禁止Tab),层级关系通过缩进表示,通常为2个空格。
- 键值对:
key: value,冒号后必须跟一个空格。 - 列表:以短横线
-开头,后跟空格。 - 多行字符串:使用
|(保留换行)或>(折叠换行)。 - 注释:以
#开头。
# 用户服务API契约片段
openapi: "3.0.3"
info:
title: 用户管理服务
version: "1.0.0"
description: 提供用户注册、登录、信息查询等接口
paths:
/users:
get:
summary: 获取用户列表
parameters:
- name: page
in: query
schema:
type: integer
default: 1
responses:
'200':
description: 成功返回用户列表
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/User'
3.2.2 JSON等价表示
{
"openapi": "3.0.3",
"info": {
"title": "用户管理服务",
"version": "1.0.0",
"description": "提供用户注册、登录、信息查询等接口"
},
"paths": {
"/users": {
"get": {
"summary": "获取用户列表",
"parameters": [
{
"name": "page",
"in": "query",
"schema": {
"type": "integer",
"default": 1
}
}
],
"responses": {
"200": {
"description": "成功返回用户列表",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/User"
}
}
}
}
}
}
}
}
}
}
3.3 契约文件结构解析
一个完整的OpenAPI契约文件由顶层对象和若干核心部分组成。下图展示了契约文件的整体骨架结构:
3.4 核心字段详解
3.4.1 info 元信息
描述API的基本信息,包括标题、版本、描述、联系方式和许可协议。这些信息会被API文档工具自动提取并展示在文档首页。
info:
title: 电商平台API
version: "2.1.0"
description: 提供商品、订单、支付等核心业务接口
contact:
name: API治理团队
email: api@example.com
license:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0
3.4.2 servers 服务地址
定义API的基础URL,支持多环境配置。每个server对象包含url和可选的description。
servers:
- url: https://api.example.com/v2
description: 生产环境
- url: https://staging-api.example.com/v2
description: 预发布环境
- url: http://localhost:8080/v2
description: 本地开发环境
3.4.3 paths 路径与操作
paths是契约文件的核心,定义了所有可用的API端点及其支持的HTTP方法。每个路径下可包含get、post、put、delete、patch等操作。
| 操作字段 | 说明 | 是否必需 |
|---|---|---|
| operationId | 操作的唯一标识符,用于代码生成和日志追踪 | 推荐 |
| summary | 简短描述,用于文档列表展示 | 推荐 |
| description | 详细描述,支持Markdown格式 | 可选 |
| parameters | 路径参数、查询参数、请求头参数的定义 | 按需 |
| requestBody | 请求体结构(仅POST/PUT/PATCH) | 按需 |
| responses | 所有可能的响应状态码及对应结构 | 必需 |
| security | 该操作的安全认证要求 | 可选 |
paths:
/orders/{orderId}:
get:
operationId: getOrderById
summary: 根据订单ID查询订单详情
parameters:
- name: orderId
in: path
required: true
schema:
type: string
pattern: '^ORD-\d{8}$'
responses:
'200':
description: 订单详情
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
'404':
description: 订单不存在
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
3.4.4 components 组件复用
components是OpenAPI 3.0引入的重要机制,用于定义可复用的模型、参数、响应和安全方案。通过$ref引用,避免重复定义,降低维护成本。
components:
schemas:
Order:
type: object
required:
- orderId
- userId
- totalAmount
- status
properties:
orderId:
type: string
description: 订单唯一编号
userId:
type: string
description: 用户ID
totalAmount:
type: number
format: float
description: 订单总金额
status:
type: string
enum:
- PENDING
- PAID
- SHIPPED
- DELIVERED
- CANCELLED
items:
type: array
items:
$ref: '#/components/schemas/OrderItem'
OrderItem:
type: object
properties:
productId:
type: string
quantity:
type: integer
minimum: 1
price:
type: number
format: float
ErrorResponse:
type: object
properties:
code:
type: string
message:
type: string
3.5 契约文件组织策略
随着API规模增长,单个契约文件会变得臃肿。推荐采用多文件组织策略,利用$ref进行跨文件引用。
api/
├── openapi.yaml # 入口文件:info、servers、paths引用
├── paths/
│ ├── users.yaml # 用户相关路径
│ ├── orders.yaml # 订单相关路径
│ └── products.yaml # 商品相关路径
└── components/
├── schemas/
│ ├── User.yaml
│ ├── Order.yaml
│ └── Product.yaml
├── parameters/
│ └── common.yaml # 分页、排序等通用参数
└── responses/
└── errors.yaml # 通用错误响应
# openapi.yaml 入口文件
openapi: "3.0.3"
info:
title: 电商平台API
version: "2.1.0"
servers:
- url: https://api.example.com/v2
paths:
/users:
$ref: './paths/users.yaml#/~1users'
/orders:
$ref: './paths/orders.yaml#/~1orders'
/products:
$ref: './paths/products.yaml#/~1products'
components:
schemas:
User:
$ref: './components/schemas/User.yaml'
Order:
$ref: './components/schemas/Order.yaml'
Product:
$ref: './components/schemas/Product.yaml'
~1 转义(~1 代表 /)。例如 #/~1users 表示 #/users。这是JSON Pointer规范的要求。
3.6 契约验证与工具链
定义完契约文件后,必须进行语法校验和规范合规性检查。以下是常用工具:
| 工具 | 用途 | 命令示例 |
|---|---|---|
| Swagger Editor | 在线编辑与实时校验 | 浏览器打开 editor.swagger.io |
| Spectral | 自定义规则 lint 检查 | spectral lint openapi.yaml |
| Redocly CLI | 预览文档、校验、打包 | redocly lint openapi.yaml |
| openapi-generator | 生成服务端/客户端代码 | openapi-generator generate -i openapi.yaml -g spring |
spectral lint 步骤,对每次契约变更进行自动化合规检查。常见规则包括:所有操作必须有 operationId、响应必须定义至少一个成功状态码、参数必须指定 schema 类型等。
3.7 从契约到Mock的桥梁
契约文件不仅是文档,更是Mock服务的直接输入源。通过解析契约中的schema定义,可以自动生成符合数据结构的Mock响应。下图展示了契约驱动Mock的核心流程:
通过上述流程,团队可以在后端接口尚未实现时,基于契约文件快速启动前端开发和自动化测试,实现真正的“契约先行”开发模式。