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
工程建议:新项目应直接采用 OpenAPI 3.0.3 或 3.1.0。3.1.0 版本与 JSON Schema 2020-12 完全兼容,支持更丰富的类型校验和描述能力。

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"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}
选型建议:在代码仓库中维护契约文件时,优先使用YAML格式,便于人工review和diff对比。在API网关或运行时解析场景下,可转换为JSON以提高解析性能。

3.3 契约文件结构解析

一个完整的OpenAPI契约文件由顶层对象和若干核心部分组成。下图展示了契约文件的整体骨架结构:

OpenAPI 契约文件结构 OpenAPI Object info servers paths components security tags externalDocs /users /orders schemas parameters responses securitySchemes paths 定义具体API端点;components 提供可复用的模型、参数和响应,减少冗余

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'
注意: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
CI/CD集成:建议在CI流水线中加入 spectral lint 步骤,对每次契约变更进行自动化合规检查。常见规则包括:所有操作必须有 operationId、响应必须定义至少一个成功状态码、参数必须指定 schema 类型等。

3.7 从契约到Mock的桥梁

契约文件不仅是文档,更是Mock服务的直接输入源。通过解析契约中的schema定义,可以自动生成符合数据结构的Mock响应。下图展示了契约驱动Mock的核心流程:

契约驱动Mock数据生成流程 OpenAPI 契约文件 openapi.yaml 契约解析引擎 解析 schema / 参数 Mock 数据生成器 根据类型/约束生成 Mock 服务 返回模拟响应 前端/测试客户端 发送请求 契约即真相:Mock数据严格遵循契约定义,确保前后端联调时数据格式一致

通过上述流程,团队可以在后端接口尚未实现时,基于契约文件快速启动前端开发和自动化测试,实现真正的“契约先行”开发模式。