Spring Boot 3 整合 springdoc-openapi
概述
springdoc-openapi
是一个用于自动生成 OpenAPI 3.0 文档的库,它支持与 Spring Boot 无缝集成。通过这个库,你可以轻松地生成和展示 RESTful API 的文档,并且可以使用 Swagger UI 或 ReDoc 进行交互式测试。
环境准备
- Spring Boot 3.x
- Java 17+
- Maven
创建 Spring Boot 项目
首先,创建一个新的 Spring Boot 项目。你可以使用 Spring Initializr 来快速生成项目结构。
添加依赖
在 pom.xml
文件中添加 springdoc-openapi-ui
依赖:
<dependencies>
<!-- Spring Web 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- springdoc-openapi-starter-webmvc-ui 是一个 Spring Boot Starter,它包含了 springdoc-openapi-ui 及其他必要的依赖,简化了依赖管理和配置 -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.6.0</version>
</dependency>
<!-- springdoc-openapi-ui 依赖 -->
<!-- <dependency>-->
<!-- <groupId>org.springdoc</groupId>-->
<!-- <artifactId>springdoc-openapi-ui</artifactId>-->
<!-- <version>1.8.0</version>-->
<!-- </dependency>-->
</dependencies>
配置文件
在 application.yml
或 application.properties
中配置 Swagger UI 和 ReDoc 的路径(可选):
springdoc:
api-docs:
path: /v3/api-docs
swagger-ui:
path: /swagger-ui.html
enabled: true
operationsSorter: method
show-actuator: true
或者在 application.properties
中:
springdoc.api-docs.path=/v3/api-docs
springdoc.swagger-ui.path=/swagger-ui.html
springdoc.swagger-ui.enabled=true
springdoc.swagger-ui.operations-sorter=method
springdoc.show-actuator=true
创建模型类
创建一个简单的模型类 User
,并使用 @Schema
注解来描述字段:
package org.springdoc.demo.services.user.model;
import io.swagger.v3.oas.annotations.media.Schema;
@Schema(name = "User", description = "用户实体")
public class User {
@Schema(description = "用户ID", example = "1", requiredMode = Schema.RequiredMode.REQUIRED)
private Long id;
@Schema(description = "用户名", example = "john_doe", requiredMode = Schema.RequiredMode.REQUIRED)
private String username;
@Schema(description = "电子邮件", example = "john.doe@example.com", requiredMode = Schema.RequiredMode.REQUIRED)
private String email;
public User(Long id, String username, String email) {
this.id = id;
this.username = username;
this.email = email;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
如何想隐藏模型的某个字段,不生成文档,可以使用@Schema(hidden = true)。
当我们的 model 包含 JSR-303 Bean 验证注解(如 @NotNull、@NotBlank、@Size、@Min 和 @Max)时,springdoc-openapi 库会使用它们为相应的约束生成额外的 schema 文档。
/*
*
* * Copyright 2019-2020 the original author or authors.
* *
* * Licensed under the Apache License, Version 2.0 (the "License");
* * you may not use this file except in compliance with the License.
* * You may obtain a copy of the License at
* *
* * https://www.apache.org/licenses/LICENSE-2.0
* *
* * Unless required by applicable law or agreed to in writing, software
* * distributed under the License is distributed on an "AS IS" BASIS,
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* * See the License for the specific language governing permissions and
* * limitations under the License.
*
*/
package org.springdoc.demo.services.book.model;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
/**
* The type Book.
*/
public class Book {
/**
* The Id.
*/
@Schema(hidden = true)
private long id;
/**
* The Title.
*/
@NotBlank
@Size(min = 0, max = 20)
private String title;
/**
* The Author.
*/
@NotBlank
@Size(min = 0, max = 30)
private String author;
}
创建 RESTful 控制器
创建一个控制器 UserController
,包含两个方法:一个使用 OpenAPI 注解,另一个不使用。
我们使用 @Operation 和 @ApiResponses 对 controller 的 /api/user/{id} 端点进行注解。 其实不使用
@Operation 和 @ApiResponses,也会生成文档,只是信息少一些。
package org.springdoc.demo.services.user.controller;
import org.springdoc.demo.services.user.model.User;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/api/user")
public class UserController {
private final Map<Long, User> userMap = new HashMap<>();
public UserController() {
// 初始化一些示例数据
userMap.put(1L, new User(1L, "john_doe", "john.doe@example.com"));
userMap.put(2L, new User(2L, "jane_doe", "jane.doe@example.com"));
}
@Operation(
summary = "获取用户信息",
description = "根据用户ID获取用户信息",
responses = {
@ApiResponse(
responseCode = "200",
description = "成功",
content = @Content(
mediaType = "application/json",
schema = @Schema(implementation = User.class)
)
),
@ApiResponse(
responseCode = "404",
description = "未找到用户"
)
}
)
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable @Parameter(description = "用户ID") Long id) {
User user = userMap.get(id);
if (user != null) {
return ResponseEntity.ok(user);
} else {
return ResponseEntity.notFound().build();
}
}
@GetMapping("/{id}/no-annotations")
public ResponseEntity<User> getUserByIdNoAnnotations(@PathVariable Long id) {
User user = userMap.get(id);
if (user != null) {
return ResponseEntity.ok(user);
} else {
return ResponseEntity.notFound().build();
}
}
}
自定义全局配置
如果你需要自定义全局的 OpenAPI 文档信息,可以创建一个配置类 OpenApiConfig
:
package com.example.demo.config;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class OpenApiConfig {
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("示例 API 文档")
.version("1.0")
.description("这是一个示例 API 文档,用于演示如何整合 springdoc-openapi。")
.contact(new Contact()
.name("你的名字")
.email("your.email@example.com")
.url("https://example.com"))
.license(new License()
.name("Apache 2.0")
.url("http://www.apache.org/licenses/LICENSE-2.0")));
}
}
启动应用
创建一个 Spring Boot 应用程序的主类:
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
访问 Swagger UI
启动应用程序后,你可以通过以下 URL 访问 Swagger UI:
http://localhost:8080/swagger-ui.html
在 Swagger UI 页面中,你可以看到生成的 API 文档,并且可以进行交互式测试。
配置分组
可以在通过配置 application.yml 来设置分组
springdoc:
api-docs:
version: openapi_3_1
path: /v3/api-docs
version: '@springdoc.version@'
swagger-ui:
path: /swagger-ui.html
enabled: true
operationsSorter: method
use-root-path: true
#包扫描路径
# packages-to-scan: com.ruoyi.tenant.controller
group-configs:
- group: user
#按包路径匹配
packagesToScan: org.springdoc.demo.services.user
- group: book
#按路径匹配
pathsToMatch: /api/book/**
#按包路径匹配
packagesToScan: org.springdoc.demo.services.book
也可以在配置类里配置
package org.springdoc.demo.services.config;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class OpenApiConfig {
@Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.info(new Info()
.title("示例 API 文档")
.version("1.0")
.description("这是一个示例 API 文档,用于演示如何整合 springdoc-openapi。")
.contact(new Contact()
.name("你的名字")
.email("your.email@example.com")
.url("https://example.com"))
.license(new License()
.name("Apache 2.0")
.url("http://www.apache.org/licenses/LICENSE-2.0")));
}
@Bean
public GroupedOpenApi userApi() {
return GroupedOpenApi.builder()
.group("user")
// .packagesToScan("org.springdoc.demo.services.user")
.pathsToMatch("/api/user/**")
.build();
}
@Bean
public GroupedOpenApi bookpi() {
return GroupedOpenApi.builder()
.group("book")
.pathsToMatch("/api/book/**")
// .packagesToScan("org.springdoc.demo.services.book")
.build();
}
}
两个方法选择一个就可以了。
总结
通过以上步骤,你已经成功地在 Spring Boot 3 项目中集成了 springdoc-openapi
,并生成了 OpenAPI 3.0 文档。你可以根据需要进一步扩展和定制文档,以满足项目的具体需求。
推荐使用 springdoc-openapi 的理由如下:
- springdoc-openapi 是 spring 官方出品,与 springboot 兼容更好(springfox 兼容有坑)
- springdoc-openapi 社区更活跃,springfox 已经 2 年没更新了 springdoc-o
- penapi 的注解更接近 OpenAPI 3 规范