1. 简介
Swagger 规范如今更常被称为 OpenAPI 规范。尽管 Smartbear 仍在维护一些工具,例如用于 Java 和 Kotlin 的 Swagger 注解,但在可能的情况下,应优先使用 OpenAPI 版本的工具和规范。
本文将讨论在项目中使用 OpenAPI 规范的优势。通常有两种使用方式:一种是已有代码,需要生成 API 规范;另一种是已有规范,需要生成代码。
无论哪种方式,OpenAPI/Swagger 工具都能为我们自动生成可视化的 API 文档页面,极大提升前后端协作效率。
2. 在 Spring Boot 项目中引入 OpenAPI
我们使用 Gradle 构建项目,通过 Spring Initializr 创建一个基于 Kotlin、Spring Web 和 JDK 17 的项目。下载并导入项目后,只需添加以下三个依赖即可启用 OpenAPI 功能:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-data-rest</artifactId>
<version>1.8.0</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
<version>1.8.0</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-kotlin</artifactId>
<version>1.8.0</version>
</dependency>
添加依赖后运行项目,访问 http://localhost:8080/swagger-ui.html 即可看到空的文档页面。接下来我们将为接口添加描述信息。
3. 从现有代码生成 OpenAPI 规范
很多项目在引入 OpenAPI 时,往往已有一定的开发历史。这些项目虽然暴露了接口,但新用户接入时往往因文档不全或过时而遇到困难。
将代码作为文档的唯一真实来源,可以确保文档始终与代码保持同步。这在对外提供 API 服务时尤为重要,因为你可以独立发布新版本接口并通知调用方更新。
3.1. 使用注解生成规范
要生成文档,我们需要对 REST 控制器和数据模型类添加注解。对于数据类,主要使用 @Schema
注解描述字段信息:
@Schema(description = "Model for a dealer's view of a car.")
data class DealerCar(
@field:Schema(
description = "A year when this car was made",
example = "2021",
type = "int",
minimum = "1900",
maximum = "2500"
)
val year: Int,
// More fields
)
对于控制器方法,我们使用 @Operation
和 @ApiResponses
注解描述接口行为和返回码:
@Operation(summary = "Sets a price for a chosen car", description = "Returns 202 if successful")
@ApiResponses(
value = [
ApiResponse(responseCode = "202", description = "Successful Operation"),
ApiResponse(responseCode = "404", description = "Such a car does not exist"),
]
)
@PostMapping("/price/{carId}", consumes = ["application/json"])
fun setPrice(
@PathVariable carId: Int,
@RequestBody @OASRequestBody(
description = "New price for the car",
content = [Content(
mediaType = "application/json",
schema = Schema(type = "number", format = "float", minimum = "0.0", example = "23000.34"),
)]
) price: BigDecimal
): ResponseEntity<Unit> {
carService.setPrice(carId, price)
return ResponseEntity.accepted().build()
}
⚠️ 注意:这种方式虽然强大,但注解数量可能迅速膨胀,影响代码可读性。如果你的接口设计变动频繁,建议优先从规范出发。
4. 从 OpenAPI 规范生成代码
无论是客户端对接还是服务端接口开发,手动编写重复的 HTTP 交互逻辑都容易出错且效率低下。通过规范生成代码,可以大幅提升开发效率。
此外,先定义规范也有助于前后端之间达成一致,避免频繁的接口变更。
4.2. 使用规范文件生成 Spring 服务端
首先,我们需要准备一个 OpenAPI 规范文件。你可以使用 Swagger 在线编辑器 编写,也可以从 GitHub 示例 获取。
然后,使用 OpenAPI Generator 插件生成服务端代码:
<plugin>
<groupId>org.openapitools</groupId>
<artifactId>openapi-generator-maven-plugin</artifactId>
<version>7.6.0</version>
<executions>
<execution>
<id>generateServer</id>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>${basedir}/src/main/resources/car-spec.yaml</inputSpec>
<generatorName>kotlin-spring</generatorName>
<packageName>com.baeldung.openapi.car</packageName>
<output>${project.build.directory}/generated-oas</output>
<configOptions>
<dateLibrary>java8</dateLibrary>
<interfaceOnly>true</interfaceOnly>
<useTags>true</useTags>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
✅ 建议:记得将生成目录加入 Kotlin 编译路径,并在 sourceSets
中配置。
插件会生成接口类,我们只需实现具体逻辑即可:
class CarCrudController(private val carService: CarService) : CarsApi {
override fun createCar(carBody: CarBody): ResponseEntity<Car> = TODO("Implementation")
override fun getCar(id: Int): ResponseEntity<Car> = TODO("Implementation")
override fun getCars(): ResponseEntity<List<Car>> = TODO("Implementation")
}
4.3. 使用规范生成客户端
与服务端类似,我们也可以从规范生成客户端代码。只需修改 generatorName
为 kotlin
即可:
<generatorName>kotlin</generatorName>
同时,添加必要的依赖支持 JSON 解析和网络请求:
<dependency>
<groupId>com.squareup.moshi</groupId>
<artifactId>moshi-kotlin</artifactId>
<version>1.13.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.moshi</groupId>
<artifactId>moshi-adapters</artifactId>
<version>1.13.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.3</version>
<scope>test</scope>
</dependency>
使用客户端非常简单:
val car = CarsApi("http://localhost:8080")
.createCar(ClientCarBody(model = "CM-X", make = "Gokyoro", year = 2021))
5. 总结
本文介绍了如何使用 OpenAPI(原 Swagger)实现以下功能:
✅ 从现有代码生成 API 规范
✅ 从规范生成服务端接口或客户端代码
✅ 自动生成用户友好的 API 文档页面
使用 OpenAPI 可以显著提升接口设计的规范性和协作效率,尤其是在跨团队或对外服务场景中。
完整代码示例可在 GitHub 上查看:kotlin-openapi 示例