1. 概述

API 文档是构建 REST 接口不可或缺的一环。本文将介绍如何使用 SpringDoc,为基于 Spring Boot 3.x 的应用快速生成和维护符合 OpenAPI 3 规范的 API 文档。

SpringDoc 极大简化了文档生成流程,开箱即用,适合现代 Spring 项目。✅

2. 集成 springdoc-openapi

Spring Boot 3.x 需要使用 springdoc-openapiv2.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,效果如下:

Swagger UI

点击 /api/book 接口,可查看详细请求/响应结构:

Swagger UI API Details

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 的标签排序遵循以下优先级:

  1. 类上使用 @Tag 且包含 descriptionexternalDocs 的标签 → 优先展示(全局标签)
  2. 其他标签按操作类型排序:PUT → POST → GET → DELETE

例如,tag_at_class_level 因在类上定义且含 description,会作为全局标签优先显示。

⚠️ 踩坑提示:仅指定 name@Tag 不会影响全局排序,仅作用于当前操作。

5.2 使用 tagsSorter 按名称排序

若想按标签名称字母排序,可在 application.properties 中配置:

springdoc.swagger-ui.tagsSorter=alpha

效果如下,标签按 createdeletefindupdate 字典序排列:

AlphaTagOrder1

5.3 使用 writer-with-order-by-keys 按路径排序

该配置基于接口路径(path)的字母序排序,且会优先显示全局标签:

springdoc.writer-with-order-by-keys=true

排序逻辑:先全局标签,再按路径 /book/deleteBookById 等字母序排列。

TagsOrderedByKey1

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 严格按照代码中声明的顺序展示标签,不受其他配置影响。

TagsOrderedRoot-1

6. 暴露分页信息(Pagination)

Spring Data JPA 的 Pageable 参数会被 SpringDoc 自动识别并生成文档。

@GetMapping("/filter")
public Page<Book> filterBooks(@ParameterObject Pageable pageable) {
     return repository.getBooks(pageable);
}

✅ 自 v1.6.0 起支持,无需额外配置。生成的文档会自动包含 pagesizesort 查询参数:

Pageable

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;
}

生成的文档会包含字段约束信息:

Book Schema After Adding Bean Validation

✅ 零配置,提升文档实用性。

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 响应码及描述:

Documentation for @ControllerAdvice and @ResponseStatus

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());
}

效果如下,接口描述清晰明了:

BooksGetByID

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

  1. Spring 的 @RequestBody:用于参数绑定,运行时必需
  2. OpenAPI 的 @RequestBody:用于文档生成,提供描述、示例等元数据

最终文档效果:

Body

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 更完整:

FooSchema

13. 总结

SpringDoc 是 Spring Boot 3.x 下生成 OpenAPI 3 文档的首选方案,具备以下优势:

✅ 开箱即用,集成简单
✅ 支持 MVC 与 WebFlux
✅ 自动生成分页、校验、异常响应文档
✅ 支持 Maven 插件,适合自动化流程
✅ 完美兼容 Kotlin
✅ 提供丰富注解,支持精细化文档控制

合理使用 SpringDoc,可大幅提升 API 可维护性与团队协作效率,建议所有 Spring Boot 项目标配接入。


原始标题:Documenting a Spring REST API Using OpenAPI 3.0 | Baeldung