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/>
- </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.(io.swagger.v3.oas.models.SpecVersion)
这个报错才是访问不到的根本原因
原因:- 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)
复制代码 精确流程
这里先提供一下目录文件:
添加精确依赖
完整的添加所有的依赖,每个依赖都不能少,少就可能出错(可解决报错一)- io.swagger.core.v3 swagger-core 2.2.20 <dependency>
- <groupId>com.github.xiaoymin</groupId>
- <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
- <version>4.4.0</version>
- </dependency> org.springdoc springdoc-openapi-starter-webmvc-api 2.2.0 org.springframework.boot spring-boot-configuration-processor true com.fasterxml.jackson.module jackson-module-jakarta-xmlbind-annotations 2.13.3 javax.xml.bind jaxb-api 2.4.0-b180830.0359
复制代码 添加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());
- }
-
- }
复制代码 配置后的结果:点击可以直接访问

如果代码写的有问题,欢迎各人评论交流,进行指点!!!
也希望各人点个关注哦~~~~~~~~
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |