Maven 生成 OpenAPI 3.0 (Swagger):Spring 项目指南
2025-03-21 06:38:36
Maven 编译时从 Spring 应用源码生成 OpenAPI 3.0 定义文件
在使用 Spring 框架(非 Spring Boot)开发 RESTful API 时,我们常常需要生成 API 文档。OpenAPI(Swagger)是一个流行的 API 文档规范。本文将介绍如何使用 Maven 插件,在编译阶段从 Spring 应用源码中提取信息,自动生成 OpenAPI 3.0 定义文件(JSON 或 YAML 格式)。
碰到的问题
你已经在 Controller 类中添加了 io.swagger.v3.oas.annotations
注解,例如:
package com.acme.rest;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
@Tag(name = "Dummy Controller", description = "Dummy controller.")
@RestController
@RequestMapping("/api/v1/dummy")
public class DummyController {
@Operation(summary = "dummy(). Does litrally nothing.")
@RequestMapping(value = "/", method = RequestMethod.GET)
public String doStuff() {
return "dummy";
}
}
并且尝试使用了 swagger-maven-plugin:
<plugin>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-maven-plugin</artifactId>
<version>2.2.0</version>
<configuration>
<outputPath>${project.build.directory}/swagger-def</outputPath>
<resourcePackages>com.acme</resourcePackages>
<prettyPrint>true</prettyPrint>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>resolve</goal>
</goals>
</execution>
</executions>
</plugin>
但是,执行 mvn clean compile
后,生成的 OpenAPI 定义文件只包含版本信息:
{
"openapi" : "3.0.1"
}
问题在于,swagger-maven-plugin
默认情况下不会自动扫描和解析 io.swagger.v3.oas.annotations
注解。 尽管注解和插件都来自io.swagger.core.v3
组。 除非提供了自定义的io.swagger.v3.oas.integration.api.OpenApiReader
和/或 io.swagger.v3.oas.integration.api.OpenApiScanner
实现, 否则它不会处理。
问题原因分析
swagger-maven-plugin
的核心逻辑依赖于 OpenApiReader
和 OpenApiScanner
接口的实现。 这两个接口负责:
- OpenApiScanner: 扫描项目中的类,识别出需要纳入 OpenAPI 定义的资源(例如,带有
@RestController
注解的类)。 - OpenApiReader: 读取类和方法上的 Swagger 注解(例如,
@Operation
,@Tag
),并将其转换为 OpenAPI 定义对象。
swagger-maven-plugin
默认提供了一个扫描器 DefaultJaxrsScanner
, 从名称就能推断它用于jax-rs, 而不是spring。 不指定自定义实现的话,插件就无法正确解析我们项目中的 Spring MVC 注解。
解决方案
方案一:提供自定义的 Scanner 和 Reader (麻烦, 不建议)
根据 官方文档 的建议, 可以添加它们的自定义实现.
<scannerClass>com.acme.util.SwaggerOpenApiScanner</scannerClass>
<readerClass>com.acme.util.SwaggerOpenApiReader</readerClass>
但老实讲, 这很不方便.
方案二: 使用 springdoc-openapi-maven-plugin
(推荐!)
springdoc-openapi-maven-plugin
是一个专门为 Spring 项目设计的 OpenAPI 生成插件,它能很好地与 Spring MVC 集成,自动识别和处理 Spring 的相关注解。
-
添加插件依赖:
在
pom.xml
文件的plugins
部分添加以下配置:<plugin> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-maven-plugin</artifactId> <version>0.3</version> <executions> <execution> <id>integration-test</id> <goals> <goal>generate</goal> </goals> </execution> </executions> <configuration> <apiDocsUrl>http://localhost:8080/v3/api-docs</apiDocsUrl> <outputFileName>openapi.json</outputFileName> <outputDir>${project.build.directory}</outputDir> </configuration> </plugin>
springdoc-openapi-maven-plugin
: 插件的坐标。version
: 插件版本。可以去maven 仓库里面找最新的稳定版。generate
: 插件目标,用于生成 OpenAPI 定义。<apiDocsUrl>
: 指向你的 Spring 应用程序的 API 文档端点。 通常,Springdoc 默认的 API 文档路径是/v3/api-docs
。 你需要启动你的 Spring 应用程序才能生成。<outputFileName>
: 指定生成的 OpenAPI 定义文件的名称(可选, 默认openapi.json
)。<outputDir>
: 指定生成的 OpenAPI 定义文件的输出目录(可选,默认${project.build.directory}
)。
-
运行插件:
首先启动你的 Spring 应用程序 (为了
springdoc-openapi-maven-plugin
可以访问)。 然后运行以下 Maven 命令:mvn clean install
生成的
openapi.json
(或你在<outputFileName>
中指定的名称)文件会出现在你配置的<outputDir>
中(默认是target
目录)。
原理和作用:
springdoc-openapi-maven-plugin
的工作原理是这样的: 它会尝试访问你指定的 apiDocsUrl
,这个 URL 应该是你的 Spring 应用提供的 OpenAPI 定义的访问地址。springdoc-openapi
库(你的 Spring 项目需要集成它)会自动根据你代码中的 Spring MVC 注解和 Swagger 注解生成 OpenAPI 定义,然后通过这个 URL 暴露出来。 springdoc-openapi-maven-plugin
拿到定义后再把它保存到本地文件中。
额外说明:
- 你的项目需要集成
springdoc-openapi
库, 使你的应用可以通过apiDocsUrl
访问 OpenAPI. 参考下方**"进阶: 搭配springdoc-openapi-ui
使用"** 。 - 确保
apiDocsUrl
正确指向你的应用, 且你的应用处于运行状态. - 这种方法是生成一个静态的 OpenAPI 文件,这个文件与实际运行的 Spring 应用程序的状态是分离的。这意味着,如果在生成文件后修改了代码,需要重新运行 Maven 插件来更新这个文件。
进阶: 搭配springdoc-openapi-ui
使用
为了使用 springdoc-openapi-maven-plugin
, 你的 Spring 项目应该能够通过某个 URL 来访问OpenAPI, springdoc-openapi-ui
就能完成这项工作:
-
添加依赖:
非 Spring Boot项目, 你应该按如下所示,手动将不同功能的 starter 加入依赖.<dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-webmvc-core</artifactId> <version>1.7.0</version> </dependency> <dependency> <groupId>org.springdoc</groupId> <artifactId>springdoc-openapi-ui</artifactId> <version>1.7.0</version> </dependency>
去 maven 仓库查询并使用最新的稳定版。
-
配置(如果必要):
通常情况下,
springdoc-openapi-ui
不需要额外配置就可以工作。 它会自动扫描你的 Spring MVC 控制器和相关的 Swagger 注解。但如果你有特殊需求,例如自定义 API 文档的路径、分组等,可以在你的 Spring 配置文件(例如,
application.properties
或 XML 配置文件)中进行设置。
举例(在XML 配置中):
```xml
<bean class="org.springdoc.core.GroupedOpenApi" id="publicApi">
<constructor-arg index="0" value="public"/>
<constructor-arg index="1">
<bean class="org.springdoc.core.GroupedOpenApi$Builder">
<property name="group" value="users"/>
<property name="pathsToMatch" value="/api/v1/user/**"/>
</bean>
</constructor-arg>
</bean>
```
- 启动应用, 就可以使用默认路径访问了
http://localhost:8080/swagger-ui.html
####方案三:自定义插件 (作为终极方案)
自己开发一个插件去实现OpenApiReader
和 OpenApiScanner
工作, 原理还是根据指定的 resourcePackages
路径去扫描和读取 class.
虽然需要对 maven 插件开发比较熟悉, 不过作为终极方案可以了解. 这里不赘述了.
总结
遇到类似的问题要善用搜索引擎与官网, 一些陈旧的方法可能已经不再适用. 比如本次 swagger-maven-plugin
就不如springdoc-openapi-maven-plugin
更方便好用。 希望以上解决方案能解决你的困惑。