SpringBoot 3.x 結合 Swagger3 (Knife4j )踩坑實錄
SpringBoot 3.x + Swagger3 踩坑實錄
我的是springboot 版本是:3.2.2
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
官方文檔
官方文檔(快速開始):
1,快速開始 | Knife4j (xiaominfo.com)
https://doc.xiaominfo.com/docs/quick-start
官方文檔(詳細配置):
2, 增強模式 | Knife4j (xiaominfo.com)
https://doc.xiaominfo.com/docs/features/enhance
3,版本參考
Knife4j版本參考 | Knife4j (xiaominfo.com)
如果自己springboot 是 2.X.X 的版本,可參考官方文檔,進行不同的依賴配置
以下是一些常見的Spring Boot版本及其對應的Knife4j版本兼容推薦:

Knife4j在之前的版本更新中,逐漸提供了一些服務端適配的增強特性功能。
但是開發者應該明白,不管是Swagger2規范還是OpenAPI3規范,Knife4j的最新版本的純Ui版本,是可以適配Spring Boot所有版本的。
如果你不考慮使用Knife4j提供的服務端增強功能,引入Knife4j的純Ui版本沒有任何限制。只需要考慮不同的規范即可
其實大部分的報錯一般都是依賴問題(比如依賴缺少,版本沖突,版本不合)
錯誤操作
依賴
網上帖子一般說的結合 knife4j(Swagger3), 添加的依賴一般都只有knife4j。 但是這個是不對的,依賴沒有完全,并且就算配置好yaml ,啟動訪問也會出錯。完整依賴可看下面正確部分。
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>4.4.0</version>
</dependency>
yaml 配置
改的地方為:packages-to-scan: com.example.eip.controller(自己項目的controller 目錄)
其他地方基本上不用改。
springdoc:
swagger-ui:
path: /swagger-ui.html
tags-sorter: alpha
operations-sorter: alpha
api-docs:
path: /v3/api-docs
group-configs:
- group: 'default'
paths-to-match: '/**'
#生成文檔所需的掃包路徑,一般為啟動類目錄
packages-to-scan: com.example.eip.controller
#knife4j配置
knife4j:
#是否啟用增強設置
enable: true
#開啟生產環境屏蔽
production: false
#是否啟用登錄認證
basic:
enable: true
username: admin
password: 123456
setting:
language: zh_cn
enable-version: true
enable-swagger-models: true
swagger-model-name: 用戶模塊
這個時候訪問是會報錯:http://localhost:8069/doc.html#/home
報錯信息解決

報錯信息一: void io.swagger.v3.oas.models.OpenAPI.
這個報錯才是訪問不到的根本原因
原因:
jakarta.servlet.ServletException: Handler dispatch failed: java.lang.NoSuchMethodError: 'void io.swagger.v3.oas.models.OpenAPI.<init>(io.swagger.v3.oas.models.SpecVersion)'
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1104)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
報錯信息二:No static resource favicon.ico 這個報錯影響使用訪問doc文檔,但是不好看
原因:spring boot3項目中瀏覽器中訪問報錯找不到favicon.ico
目前springfox已經停止維護了。最近在升級底層框架時看到spring官方推薦使用springdoc,
這個情況有人去Github提了issue,但是Spring開發老哥說了這個不是bug,那就只能自己解決了。

org.springframework.web.servlet.resource.NoResourceFoundException: No static resource favicon.ico.
at org.springframework.web.servlet.resource.ResourceHttpRequestHandler.handleRequest(ResourceHttpRequestHandler.java:585)
at org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter.handle(HttpRequestHandlerAdapter.java:52)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:903)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:564)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885)
at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:205)
正確流程
這里先提供一下目錄文件:

添加正確依賴
完整的添加所有的依賴,每個依賴都不能少,少就可能出錯(可解決報錯一)
<!-- 添加swagger核心依賴-->
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-core</artifactId>
<version>2.2.20</version>
</dependency>
<!--添加knife4j依賴-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
<version>4.4.0</version>
</dependency>
<!--添加Springdoc依賴-->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!--僅添加上述依賴,仍有可能報錯,需補充以下依賴-->
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jakarta-xmlbind-annotations</artifactId>
<version>2.13.3</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.4.0-b180830.0359</version>
</dependency>
添加yaml 配置
springdoc:
swagger-ui:
path: /swagger-ui.html
tags-sorter: alpha
operations-sorter: alpha
api-docs:
path: /v3/api-docs
group-configs:
- group: 'default'
paths-to-match: '/**'
#生成文檔所需的掃包路徑,一般為啟動類目錄
packages-to-scan: com.example.eip.controller
#knife4j配置
knife4j:
#是否啟用增強設置
enable: true
#開啟生產環境屏蔽
production: false
#是否啟用登錄認證
basic:
enable: true
username: admin
password: 123456
setting:
language: zh_cn
enable-version: true
enable-swagger-models: true
swagger-model-name: 用戶模塊
配置過濾靜態資源
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.http.HttpStatus;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @Classname FaviconConfiguration
* @Description 添加配置文件,處理favicon.ico請求
* @Version 1.0.0
* @Date 2024/6/11 13:39
* @Created by Administrator
*/
@SpringBootConfiguration
public class FaviconConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new HandlerInterceptor() {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if (!"GET".equalsIgnoreCase(request.getMethod()) || !request.getRequestURI().toString().equals("/favicon.ico")) {
return true;
}
response.setStatus(HttpStatus.NO_CONTENT.value()); // 設置狀態碼為204 No Content
return false;
}
}).addPathPatterns("/**");
}
}
這個時候就可以訪問到文檔:http://localhost:8069/doc.html#/home
增強模式
編寫配置文件
這個部分注意是提供一些項目信息或者個人的信息
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.ExternalDocumentation;
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;
/**
* @Classname SwaggerConfig
* @Description TODO
* @Version 1.0.0
* @Date 2024/6/11 14:16
* @Created by Administrator
*/
@Configuration
public class SwaggerConfig {
@Bean
public OpenAPI swaggerOpenAPI(){
return new OpenAPI()
.info(new Info().title("標題")
// 信息
.contact(new Contact().name("作者").email("郵箱").url("地址"))
// 簡介
.description("我的API文檔")
// 版本
.version("v1")
// 許可證
.license(new License().name("Apache 2.0").url("http://springdoc.org")))
.externalDocs(new ExternalDocumentation()
.description("外部文檔")
.url("https://springshop.wiki.github.org/docs"));
}
}
配置后的效果:

配置啟動鏈接接口地址
每次都要打開瀏覽器輸入地址訪問不友好,我們在啟動類似進行地址配置
啟動類上優化 或者 編寫配置類
第一種方式: 編寫配置類(推薦使用)
創建文件:DocumentationConfig
import io.micrometer.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* @Classname DocumentationConfig
* @Description TODO
* @Version 1.0.0
* @Date 2024/6/11 15:28
* @Created by Administrator
*/
@Configuration
@Slf4j
public class DocumentationConfig {
public void logApplicationStartup(Environment env) {
String protocol = "http";
if (env.getProperty("server.ssl.key-store") != null) {
protocol = "https";
}
String serverPort = env.getProperty("server.port");
String contextPath = env.getProperty("server.servlet.context-path");
if (StringUtils.isBlank(contextPath)) {
contextPath = "/doc.html";
} else {
contextPath = contextPath + "/doc.html";
}
String hostAddress = "localhost";
try {
hostAddress = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
log.warn("The host name could not be determined, using `localhost` as fallback");
}
log.info("""
----------------------------------------------------------
\t應用程序“{}”正在運行中......
\t接口文檔訪問 URL:
\t本地: \t\t{}://localhost:{}{}
\t外部: \t{}://{}:{}{}
\t配置文件: \t{}
----------------------------------------------------------""",
env.getProperty("spring.application.name"),
protocol,
serverPort,
contextPath,
protocol,
hostAddress,
serverPort,
contextPath,
env.getActiveProfiles());
}
}
第二種方式:啟動類上優化
import io.micrometer.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.Environment;
import java.net.InetAddress;
import java.net.UnknownHostException;
@SpringBootApplication
@MapperScan("com.mijiu.mapper")
@Slf4j
public class SpringbootTemplateApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(SpringbootTemplateApplication.class);
Environment env = app.run(args).getEnvironment();
app.setBannerMode(Banner.Mode.CONSOLE);
logApplicationStartup(env);
}
private static void logApplicationStartup(Environment env) {
String protocol = "http";
if (env.getProperty("server.ssl.key-store") != null) {
protocol = "https";
}
String serverPort = env.getProperty("server.port");
String contextPath = env.getProperty("server.servlet.context-path");
if (StringUtils.isBlank(contextPath)) {
contextPath = "/doc.html";
} else {
contextPath = contextPath + "/doc.html";
}
String hostAddress = "localhost";
try {
hostAddress = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
log.warn("The host name could not be determined, using `localhost` as fallback");
}
log.info("""
----------------------------------------------------------
\t應用程序“{}”正在運行中......
\t接口文檔訪問 URL:
\t本地: \t\t{}://localhost:{}{}
\t外部: \t{}://{}:{}{}
\t配置文件: \t{}
----------------------------------------------------------""",
env.getProperty("spring.application.name"),
protocol,
serverPort,
contextPath,
protocol,
hostAddress,
serverPort,
contextPath,
env.getActiveProfiles());
}
}
配置后的效果:點擊可以直接訪問

如果代碼寫的有問題,歡迎大家評論交流,進行指點!!!
也希望大家點個關注哦~~~~~~~~

浙公網安備 33010602011771號