1. 概述
API 文档是构建 REST 接口不可或缺的一环。本文将介绍如何使用 SpringDoc,为基于 Spring Boot 3.x 的应用快速生成和维护符合 OpenAPI 3 规范的 API 文档。
SpringDoc 极大简化了文档生成流程,开箱即用,适合现代 Spring 项目。✅
2. 集成 springdoc-openapi
Spring Boot 3.x 需要使用 springdoc-openapi
的 v2.x 版本,推荐使用最新稳定版。以下是 Maven 依赖配置:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.8.5</version>
</dependency>
⚠️ 注意版本兼容性:务必参考 官方兼容性矩阵,确保 springdoc-openapi
与当前 Spring Boot 版本匹配,否则可能启动报错。
2.1 自定义 OpenAPI 文档路径
添加依赖后,应用启动后默认可通过以下路径访问 OpenAPI JSON 定义:
http://localhost:8080/v3/api-docs
如需修改该路径,可在 application.properties
中配置:
springdoc.api-docs.path=/api-docs
修改后访问路径变为:
http://localhost:8080/api-docs
默认返回 JSON 格式。若需 YAML 格式,只需在路径后加 .yaml
:
http://localhost:8080/api-docs.yaml
简单粗暴,无需额外配置。
3. 集成 Swagger UI
除了生成 OpenAPI 定义,SpringDoc 还内置了 Swagger UI,可提供可视化交互式文档界面。
✅ springdoc-openapi-starter-webmvc-ui
依赖已包含 Swagger UI,无需额外引入。
启动应用后,直接访问:
http://localhost:8080/swagger-ui/index.html
即可查看交互式 API 文档。
3.1 自定义 Swagger UI 配置
SpringDoc 支持通过 springdoc.swagger-ui
前缀的属性自定义 Swagger UI 行为。
常见配置如下:
# 自定义 UI 访问路径
springdoc.swagger-ui.path=/docs.html
# 按 HTTP 方法排序接口(PUT → POST → GET → DELETE)
springdoc.swagger-ui.operationsSorter=method
配置后,Swagger UI 将在 /docs.html
可访问,且接口按 HTTP 方法排序,更符合 RESTful 设计习惯。
3.2 示例接口展示
假设我们有一个 BookController
:
@RestController
@RequestMapping("/api/book")
public class BookController {
@Autowired
private BookRepository repository;
@GetMapping("/{id}")
public Book findById(@PathVariable long id) {
return repository.findById(id)
.orElseThrow(() -> new BookNotFoundException());
}
@GetMapping("/")
public Collection<Book> findBooks() {
return repository.getBooks();
}
@PutMapping("/{id}")
@ResponseStatus(HttpStatus.OK)
public Book updateBook(
@PathVariable("id") final String id, @RequestBody final Book book) {
return book;
}
}
启动后访问 http://localhost:8080/docs.html
,效果如下:
点击 /api/book
接口,可查看详细请求/响应结构:
4. 与 Spring WebFlux 集成
若项目使用的是响应式编程模型(WebFlux),只需替换依赖为:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webflux-ui</artifactId>
<version>2.8.5</version>
</dependency>
其余配置完全一致,Swagger UI 路径和行为不变,无缝支持响应式接口文档生成。✅
5. 使用标签(Tags)组织接口
OpenAPI 支持通过 Tags 对接口进行分类分组。Swagger UI 会根据 Tags 将接口归类展示,提升可读性。
Tags 可作用于类或方法级别,使用 @Tag
注解:
@Tag(name = "tag_at_class_level", description = "Books related class level tag")
public class BooksController {
@Tag(name = "create")
@Tag(name = "common_tag_at_method_level")
@Tag(name = "createBook")
@PostMapping(path = "/book")
@io.swagger.v3.oas.annotations.parameters.RequestBody(required = true)
public Book book(@Valid @RequestBody Book book) {
return book;
}
@Tag(name = "find")
@Tag(name = "common_tag_at_method_level")
@Tag(name = "findBook", description = "Find Books related tag")
@GetMapping(path = "/findBookById")
public List findById(@RequestParam(name = "id", required = true)
@NotNull @NotBlank @Size(max = 10) long id) {
List bookList = new ArrayList<>();
Book book = new Book();
book.setId(1);
bookList.add(book);
return bookList;
}
// delete 和 update 方法略...
}
5.1 默认标签排序规则
默认情况下,Swagger UI 的标签排序遵循以下优先级:
- 类上使用
@Tag
且包含description
或externalDocs
的标签 → 优先展示(全局标签) - 其他标签按操作类型排序:PUT → POST → GET → DELETE
例如,tag_at_class_level
因在类上定义且含 description
,会作为全局标签优先显示。
⚠️ 踩坑提示:仅指定 name
的 @Tag
不会影响全局排序,仅作用于当前操作。
5.2 使用 tagsSorter
按名称排序
若想按标签名称字母排序,可在 application.properties
中配置:
springdoc.swagger-ui.tagsSorter=alpha
效果如下,标签按 create
、delete
、find
、update
字典序排列:
5.3 使用 writer-with-order-by-keys
按路径排序
该配置基于接口路径(path)的字母序排序,且会优先显示全局标签:
springdoc.writer-with-order-by-keys=true
排序逻辑:先全局标签,再按路径 /book
、/deleteBookById
等字母序排列。
5.4 使用全局 tags
定义精确排序
最灵活的方式是通过 @OpenAPIDefinition
注解在代码中显式定义标签顺序:
@OpenAPIDefinition(tags = {
@Tag(name = "create", description = "Add book to inventory"),
@Tag(name = "delete", description = "Delete book from inventory"),
@Tag(name = "find", description = "Find book from inventory"),
@Tag(name = "update", description = "Update book in inventory")
})
public class BooksController_2 { ... }
✅ 效果:Swagger UI 严格按照代码中声明的顺序展示标签,不受其他配置影响。
6. 暴露分页信息(Pagination)
Spring Data JPA 的 Pageable
参数会被 SpringDoc 自动识别并生成文档。
@GetMapping("/filter")
public Page<Book> filterBooks(@ParameterObject Pageable pageable) {
return repository.getBooks(pageable);
}
✅ 自 v1.6.0 起支持,无需额外配置。生成的文档会自动包含 page
、size
、sort
查询参数:
7. 使用 springdoc-openapi Maven 插件
SpringDoc 提供 Maven 插件,可在构建时生成 OpenAPI 文档文件(JSON/YAML)。
需配合 spring-boot-maven-plugin
使用,在 integration-test
阶段执行:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.4.3</version>
<executions>
<execution>
<id>pre-integration-test</id>
<goals>
<goal>start</goal>
</goals>
</execution>
<execution>
<id>post-integration-test</id>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-maven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<phase>integration-test</phase>
<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>
常用配置项:
apiDocsUrl
:文档 JSON 接口地址outputFileName
:输出文件名(默认openapi.json
)outputDir
:输出目录(默认target/
)
适用于 CI/CD 场景,自动化生成 API 合同。
8. 基于 JSR-303 注解自动生成文档
实体类中的 Bean Validation 注解(如 @NotBlank
、@Size
)会被 SpringDoc 自动提取,生成更详细的 Schema 说明。
public class Book {
private long id;
@NotBlank
@Size(min = 0, max = 20)
private String title;
@NotBlank
@Size(min = 0, max = 30)
private String author;
}
生成的文档会包含字段约束信息:
✅ 零配置,提升文档实用性。
9. 使用 @ControllerAdvice 和 @ResponseStatus 生成错误码文档
在全局异常处理器中使用 @ResponseStatus
,可自动将响应码写入 OpenAPI 文档。
@RestControllerAdvice
public class GlobalControllerExceptionHandler {
@ExceptionHandler(ConversionFailedException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ResponseEntity<String> handleConversion(RuntimeException ex) {
return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(BookNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public ResponseEntity<String> handleBookNotFound(RuntimeException ex) {
return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
}
}
✅ 效果:Swagger UI 中会自动展示 400 和 404 响应码及描述:
10. 使用 @Operation 和 @ApiResponses 添加接口描述
使用 OpenAPI 注解可精细化控制文档内容。
@Operation(summary = "Get a book by its id")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "Found the book",
content = { @Content(mediaType = "application/json",
schema = @Schema(implementation = Book.class)) }),
@ApiResponse(responseCode = "400", description = "Invalid id supplied",
content = @Content),
@ApiResponse(responseCode = "404", description = "Book not found",
content = @Content) })
@GetMapping("/{id}")
public Book findById(@Parameter(description = "id of book to be searched")
@PathVariable long id) {
return repository.findById(id).orElseThrow(() -> new BookNotFoundException());
}
效果如下,接口描述清晰明了:
11. 描述请求体(Request Body)
使用 OpenAPI 的 @RequestBody
注解可详细描述请求体结构,包括示例、是否必填等。
@Operation(summary = "Create a new book")
@ApiResponses(value = {
@ApiResponse(responseCode = "201", description = "Book created successfully",
content = { @Content(mediaType = "application/json",
schema = @Schema(implementation = Book.class)) }),
@ApiResponse(responseCode = "400", description = "Invalid input provided") })
@PostMapping("/")
public Book createBook(@io.swagger.v3.oas.annotations.parameters.RequestBody(
description = "Book to create", required = true,
content = @Content(mediaType = "application/json",
schema = @Schema(implementation = Book.class),
examples = @ExampleObject(value = "{ \"title\": \"New Book\", \"author\": \"Author Name\" }")))
@RequestBody Book book) {
return repository.save(book);
}
⚠️ 注意:此处使用了两个 @RequestBody
:
- Spring 的
@RequestBody
:用于参数绑定,运行时必需 - OpenAPI 的
@RequestBody
:用于文档生成,提供描述、示例等元数据
最终文档效果:
12. Kotlin 支持
Spring Boot 3.x 原生支持 Kotlin,SpringDoc 也能完美解析 Kotlin 类型。
示例 Kotlin 控制器:
@Entity
data class Foo(
@Id
val id: Long = 0,
@NotBlank
@Size(min = 0, max = 50)
val name: String = ""
)
@RestController
@RequestMapping("/")
class FooController() {
val fooList: List<Foo> = listOf(Foo(1, "one"), Foo(2, "two"))
@Operation(summary = "Get all foos")
@ApiResponses(value = [
ApiResponse(responseCode = "200", description = "Found Foos", content = [
Content(mediaType = "application/json", array =
ArraySchema(schema = Schema(implementation = Foo::class))))]),
ApiResponse(responseCode = "400", description = "Bad request", content = [Content()]),
ApiResponse(responseCode = "404", description = "Did not find any Foos", content = [Content()])]
)
@GetMapping("/foo")
fun getAllFoos(): List<Foo> = fooList
}
为更好支持 Kotlin,可添加:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-common</artifactId>
<version>2.8.5</version>
</dependency>
生成的 Schema 更完整:
13. 总结
SpringDoc 是 Spring Boot 3.x 下生成 OpenAPI 3 文档的首选方案,具备以下优势:
✅ 开箱即用,集成简单
✅ 支持 MVC 与 WebFlux
✅ 自动生成分页、校验、异常响应文档
✅ 支持 Maven 插件,适合自动化流程
✅ 完美兼容 Kotlin
✅ 提供丰富注解,支持精细化文档控制
合理使用 SpringDoc,可大幅提升 API 可维护性与团队协作效率,建议所有 Spring Boot 项目标配接入。