1. 引言
软件工程行业对 Web API 的依赖日益加深,这主要归因于云计算和 HTTP 协议的普及。开发团队必须确保设计出实用且友好的 API。传统开发方法的核心痛点在于:在同步创建 API 契约和实现业务逻辑时,难以保持敏捷性。
本文将介绍使用 Spring Boot 和 OpenAPI 3.0 规范的 API 优先开发方法。这种方式通过及时的 API 设计反馈、快速失败流程和并行工作,显著提升团队沟通效率和敏捷性。
2. OpenAPI 规范是什么
OpenAPI 规范(OAS)标准化了 API 设计文档的创建方式。使用 OAS 的 API 优先工作流通常包含以下步骤:
- 团队创建设计文档,分享给相关方收集反馈并迭代修改
- 当团队与利益相关者达成 API 设计共识后,开发者通过代码生成工具基于文档创建服务端骨架代码
- 开发者基于生成的代码开始实现业务逻辑
OAS 3.1 支持定义 HTTP 资源、动词、响应码、数据模型、媒体类型、安全方案等 API 组件。
3. 为什么选择 API 优先开发
敏捷开发 是软件行业最主流的方法论之一。敏捷的核心在于:快速构建最小可行产品,要么快速失败并调整初始设计,要么在此基础上逐步迭代。
从敏捷团队视角看,API 优先开发具备明显优势:
- ✅ 快速获取 API 设计反馈
- ✅ 建立 API 契约共识的单一沟通渠道
- ✅ 支持相关人员并行工作
为充分理解 API 优先的优势,我们对比两个敏捷团队的工作场景:传统开发 vs API 优先开发:
在传统场景中,开发者接到新功能开发任务后,通常先实现业务逻辑,再将其与代码中的 API 设计关联。只有当开发者完成该功能的所有代码修改后,API 才能供利益相关者评审。这导致 API 契约评审和共识过程缓慢且容易产生误解。
而在 API 优先开发中,设计师在业务逻辑开发阶段前就创建 API 契约文档。该文档为产品利益相关者提供了评估工作量、及时反馈、创建测试用例、编写 API 文档等的通用语言。我们可以在浪费任何开发时间前,快速调整初始设计或推进实施,显著提升敏捷性。
API 优先开发的另一个核心优势是:文档创建后,多人可并行推进同一功能开发,例如:
- 产品经理评估风险、设计新功能、管理时间线
- 测试工程师构建测试场景
- 技术文档工程师编写 API 文档
- 开发者实现业务逻辑代码
4. 定义 API 契约
我们通过一个银行演示 REST API 说明 API 优先工作流。该 API 支持查询余额和存款操作。下表展示了资源路径、HTTP 动词和响应码(RC):
HTTP 动词 | 资源 | 错误响应码 | 成功响应码 |
---|---|---|---|
GET | /account | 404 – 账户不存在 | 200 – 获取余额信息 |
POST | /account/deposit | 404 – 账户不存在 | 204 – 存款操作完成 |
现在创建 OAS API 规范文件。我们将使用 Swagger 在线编辑器,这是一个将 YAML 解析为 Swagger 文档的在线工具。
4.1. API 顶层上下文
首先定义 API 的顶层上下文。在 Swagger 编辑器 中,用以下 YAML 代码替换编辑器左侧内容:
openapi: 3.0.3
info:
title: 银行账户操作 API 规范
description: |-
简单的银行 API,支持两种操作:
- 根据账号查询账户余额
- 向指定账户存款
version: 1.0-SNAPSHOT
servers:
- url: https://testenvironment.org/api/v1
- url: https://prodenvironment.org/api/v1
tags:
- name: accounts
description: 银行账户相关操作
⚠️ 注意:当前出现的错误可忽略,它们不会阻塞工作流,后续步骤会自动解决。
逐个解析关键字:
- openapi – 使用的 OAS 版本
- title – API 的简短标题
- description – API 职责描述
- version – API 当前版本(如 1.0-SNAPSHOT)
- servers – 客户端可访问 API 的服务器地址
- tags – 用于对 API 操作分组的唯一标签集合
4.2. 暴露 API 路径
现在创建前文描述的 GET /account 和 POST /account/deposit 接口。在 YAML 编辑器根级别添加以下内容:
paths:
/account:
get:
tags:
- accounts
summary: 获取账户信息
description: 根据账号获取账户信息
operationId: getAccount
responses:
200:
description: 成功
content:
application/json:
schema:
$ref: '#/components/schemas/Account'
404:
description: 账户不存在
content:
application/json:
schema:
$ref: '#/components/schemas/AccountNotFoundError'
/account/deposit:
post:
tags:
- accounts
summary: 向账户存款
description: 向指定账户存入指定金额
operationId: depositToAccount
requestBody:
description: 账号和存款金额
content:
application/json:
schema:
$ref: '#/components/schemas/DepositRequest'
required: true
responses:
204:
description: 成功
404:
description: 账户不存在
content:
application/json:
schema:
$ref: '#/components/schemas/AccountNotFoundError'
⚠️ 注意:YAML 解释器会显示错误,我们将在 4.3 节解决,当前可忽略。
上述文档内容较多,逐个解析关键字:
- paths – 定义 API 资源 /account 和 /account/deposit,需指定支持的 get 和 post 动词
- tags – 所属分组(需与 4.1 节的标签名一致)
- summary – 接口功能的简要说明
- description – 接口工作原理的详细说明
- operationId – 操作的唯一标识符
- requestBody – 请求载荷,包含 description、content 和 required 关键字(内容 schema 在 4.3 节定义)
- responses – 所有可用响应码列表,每个响应码对象包含 description 和 content(内容 schema 在 4.3 节定义)
- content – 消息的 HTTP Content-Type
4.3. 定义数据模型组件
最后创建 API 的数据模型对象:请求/响应体和错误消息。在 YAML 编辑器根级别添加以下结构:
components:
schemas:
Account:
type: object
properties:
balance:
type: number
AccountNotFoundError:
type: object
properties:
message:
type: string
DepositRequest:
type: object
properties:
accountNumber:
type: string
depositAmount:
type: number
添加上述内容后,编辑器中的所有解释错误应消失。
上述 YAML 代码定义了 4.2 节 schema 关键字中使用的组件。组件可无限次复用,例如 AccountNotFoundError 对象同时用于两个接口的 404 响应。逐个解析关键字:
- components – 组件的根级别关键字
- schemas – 所有对象定义的列表
- type – 字段类型(使用 object 类型时必须定义 properties)
- properties – 对象所有字段名及其类型的列表
4.4. 评审 API 文档
此时 API 已在线可供产品利益相关者评审。API 优先开发的核心优势在于:无需进入开发阶段就能快速验证设计可行性。因此,在进入开发阶段前,务必确保所有相关人员评审并确认 API 资源、响应码、数据模型及接口描述。
一旦团队达成设计共识,即可并行推进 API 开发工作。
5. 导入 Spring Boot 应用
本节展示开发者如何将 YAML 文档导入应用并自动生成 API 骨架代码。
首先在 /src/main/resources 文件夹创建空 YAML 文件 account_api_description.yaml,将 Swagger 在线编辑器中的完整 YAML 代码粘贴其中。然后在 Spring Boot 应用的 pom.xml 文件
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>6.2.1</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<skipValidateSpec>true</skipValidateSpec>
<inputSpec>./src/main/resources/account_api_description.yaml</inputSpec>
<generatorName>spring</generatorName>
<configOptions>
<openApiNullable>false</openApiNullable>
<interfaceOnly>true</interfaceOnly>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
本文代码参考自 OpenAPI 插件教程
现在运行以下命令从 YAML 文件生成服务端代码:
mvn clean install
完成后可在 target 文件夹查看生成的代码:
开发者可将生成的类作为开发阶段的起点。例如通过以下 AccountController 类实现 AccountApi 接口:
@Controller
public class AccountController implements AccountApi {
@Override
public ResponseEntity<Void> depositToAccount(DepositRequest depositRequest) {
// 通过 Service/Utils/Repository 类执行业务逻辑
return AccountApi.super.depositToAccount(depositRequest);
}
@Override
public ResponseEntity<Account> getAccount() {
// 通过 Service/Utils/Repository 类执行业务逻辑
return AccountApi.super.getAccount();
}
}
重写的 depositToAccount 和 getAccount 方法分别对应 POST /account/deposit 和 GET /account 接口。
6. 结论
本文介绍了使用 Spring Boot 和 OAS 进行 API 优先开发的方法,分析了 API 优先的优势及其对现代敏捷开发团队的助力。采用 API 优先的核心价值在于:提升敏捷性,减少 API 开发中的时间浪费。通过该方法,我们能快速起草、迭代设计并获取反馈。
采用 API 优先的另一重要原因是:利益相关者无需等待开发者完成代码即可启动工作。在初始 API 设计文档创建后,测试、文档、管理和开发人员可并行推进工作。
如往常一样,本文代码可在 GitHub 获取。