引言
使用 JDK 21 版本的 Spring Boot 项目,在整合 Swagger3 过程中遇到一些问题。网上很多关于 Spring Boot 3 整合 Knife4j 的步骤完全照着做会有问题,现将遇到的问题做记录。
Spring Boot 3 整合 Knife4j (Swagger3) 关键点梳理
1. 添加/修改依赖
Spring Boot 3.x 必须使用 knife4j-openapi3-jakarta(Jakarta 命名空间)。
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>4.5.0</version>
</dependency>
网上很多文章建议使用旧版 knife4j-spring-boot-starter,但在实际调试中会遇到很多问题,建议优先选择 Spring Boot 3.x 版本兼容的 Knife4j 版本。
2. 添加配置文件
需要配置 OpenAPI Bean 及分组扫描路径。
package com.Knife4j;
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;
import org.springdoc.core.customizers.GlobalOpenApiCustomizer;
import org.springdoc.core.models.GroupedOpenApi;
@Configuration
public class Knife4jConfig {
private static final String SERVICE_URL ;
;
;
;
;
;
;
GroupedOpenApi {
GroupedOpenApi.builder()
.group()
.displayName()
.packagesToScan()
.addOpenApiCustomizer(::setCustomStatusCode)
.build();
}
GroupedOpenApi {
GroupedOpenApi.builder()
.group()
.displayName()
.packagesToScan()
.addOpenApiCustomizer(::setCustomStatusCode)
.build();
}
GroupedOpenApi {
GroupedOpenApi.builder()
.group()
.displayName()
.packagesToScan()
.addOpenApiMethodFilter(method -> method.isAnnotationPresent(io.swagger.v3.oas.annotations.Operation.class))
.addOpenApiCustomizer(::setCustomStatusCode)
.build();
}
OpenAPI {
()
.info( ()
.title(API_INFO_TITLE)
.description(API_INFO_DESCRIPTION)
.version(API_INFO_VERSION)
.contact( ().name(API_INFO_NAME).email(API_INFO_EMAIL))
.license( ().name(API_INFO_LICENSE).url(SERVICE_URL)));
}
{
(openApi.getPaths() != ) {
( entry : openApi.getPaths().entrySet()) {
entry.getValue();
Map.of(
, pathItem.getPut(),
, pathItem.getGet(),
, pathItem.getDelete(),
, pathItem.getPost()
);
operationMap.forEach((k, v) -> {
(v != ) v.setResponses(handleResponses(v.getResponses()));
});
}
}
}
ApiResponses {
();
( entry : responses.entrySet()) {
(entry.getValue() != ) {
content = entry.getValue().getContent();
;
}
}
Map<Integer, String> map = StatusCode.toMap();
( entry : map.entrySet()) {
();
api.setContent(content);
api.description(entry.getValue());
responses.addApiResponse(entry.getKey() + , api);
}
responses;
}
GlobalOpenApiCustomizer {
openApi -> {
(openApi.getTags() != ) {
openApi.getTags().forEach(tag -> {
Map<String, Object> map = <>();
map.put(, );
tag.setExtensions(map);
});
}
(openApi.getPaths() != ) {
openApi.addExtension(, );
openApi.getPaths().addExtension(, );
}
};
}
}

