SpringBoot 3.x 结合 Swagger3 (Knife4j )踩坑实录

news/2024/9/24 17:21:14

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.htmltags-sorter: alphaoperations-sorter: alphaapi-docs:path: /v3/api-docsgroup-configs:- group: 'default'paths-to-match: '/**'#生成文档所需的扫包路径,一般为启动类目录packages-to-scan: com.example.eip.controller #knife4j配置
knife4j:#是否启用增强设置enable: true#开启生产环境屏蔽production: false#是否启用登录认证basic:enable: trueusername: adminpassword: 123456setting:language: zh_cnenable-version: trueenable-swagger-models: trueswagger-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,那就只能自己解决了。

2024-05-17T16:41:52-dvhtzz.png

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.htmltags-sorter: alphaoperations-sorter: alphaapi-docs:path: /v3/api-docsgroup-configs:- group: 'default'paths-to-match: '/**'#生成文档所需的扫包路径,一般为启动类目录packages-to-scan: com.example.eip.controller #knife4j配置
knife4j:#是否启用增强设置enable: true#开启生产环境屏蔽production: false#是否启用登录认证basic:enable: trueusername: adminpassword: 123456setting:language: zh_cnenable-version: trueenable-swagger-models: trueswagger-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 {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new HandlerInterceptor() {@Overridepublic 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 Contentreturn 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 {@Beanpublic 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());}}

配置后的效果:点击可以直接访问

如果代码写的有问题,欢迎大家评论交流,进行指点!!!

也希望大家点个关注哦~~~~~~~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/46495.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

查询windows内存卡槽及卡槽支持的最大内存

以管理员运行cmd,输入命令 wmic Memphysical get MaxCapacity, MemoryDevices如图,我本机的卡槽数量有4个,每个卡槽最大支持128G惜秦皇汉武,略输文采;唐宗宋祖,稍逊风骚。 一代天骄,成吉思汗,只识弯弓射大雕。 俱往矣,数风流人物,还看今朝

在线方式部署k8s+prometheus集群(kubesphere环境)

前言:半月前在公司生产环境上离线部署了k8s集群 和 Prometheus+Grafana监控平台的搭建,下面我租用3台华为云服务器演示在线方式部署k8s(单master节点)+prometheus集群。下期再出一版离线方式部署k8s(双master节点)集群。 安装步骤: 安装Docker 安装Kubernetes 安装KubeSp…

MURF3040CT-ASEMI无人机专用MURF3040CT

MURF3040CT-ASEMI无人机专用MURF3040CT编辑:ll MURF3040CT-ASEMI无人机专用MURF3040CT 型号:MURF3040CT 品牌:ASEMI 封装:TO-220F 最大平均正向电流(IF):30A 最大循环峰值反向电压(VRRM):400V 最大正向电压(VF):0.95V~1.90V 工作温度:-50C~150C 反向恢复时间:35…

Debian12 安装kubernetes

PrerequisitesMinimal Installed Debian 12 /11 2 CPU / vCPU 2 GB RAM 20 GB free disk space Sudo User with Admin rights Stable Internet Connectivity Ensure that each node can communicate with the others via a reliable network connection.1. 设置hostname和hosts…

ConcurrentHashMap(并发工具类)

并发工具类 在JDK的并发包里提供了几个非常有用的并发容器和并发工具类。供我们在多线程开发中进行使用。 5.1 ConcurrentHashMap 5.1.1 概述以及基本使用 在集合类中HashMap是比较常用的集合对象,但是HashMap是线程不安全的(多线程环境下可能会存在问题)。为了保证数据的安全…

GPIO的工作模式

输入模式: 输入浮空、输入上拉、输入下拉、模拟输入 输出模式: 开漏输出、开漏复用功能、推挽式输出、推挽式输出复用功能 输入浮空:输入上拉:输入下拉:开漏输出:开漏复用功能:推挽式输出:推挽式输出复用功能:

NSIS 入门教程 (一)

介绍 大多数应用程序都附带一个安装程序,它将所需的文件复制到正确的文件夹中,创建注册表项,并提供卸载例程以(希望)从计算机中彻底删除应用程序有多种解决方案可以为自主开发的应用程序配备安装程序。除了Install Shield或Wise等商业产品外,还有开源安装工具Nullsoft Sc…

02_前端HTML5

文档:HTML5 简介 (w3school.com.cn) 1.h标签定义网页中的标题,h1-h6 2.p标签用于表示网页中的段落,一般会把一段文字放在p标签内 3.span标签一般用于表示网页中的行业元素,或者是对一部分内容生效,通常和css一起使用 3.strong标签用来加粗 4.em标签用于斜体 5.ul li标签表…