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.(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)

正确流程

这里先提供一下目录文件:

添加正确依赖

完整的添加所有的依赖,每个依赖都不能少,少就可能出错(可解决报错一)

<!--   添加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());
} }

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

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

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

SpringBoot 3.x 结合 Swagger3 (Knife4j )踩坑实录的更多相关文章

  1. 后端路由项目由 gulp 改为 webpack 的踩坑实录

    前言 公司有个后端路由的项目是用 gulp 作为前端自动化构建工具,最近学习了一下 webpack,深感其强大,一狠心将其改成了 webpack 构建,以下是踩坑实录. gulp 先来说说原来的架构. ...

  2. JAVA实用案例之文件导出(JasperReport踩坑实录)

    写在最前面 想想来新公司也快五个月了,恍惚一瞬间. 翻了翻博客,因为太忙,也有将近五个多月没认真总结过了. 正好趁着今天老婆出门团建的机会,记录下最近这段时间遇到的大坑-JasperReport. 六 ...

  3. ffmpeg 踩坑实录 添加实时水印(二)

    一.背景介绍 最近领导要求做一个视频录制的相关项目.其中,需要对视频文件进行添加 实时时间水印.于是,我想到了使用之前的ffmpeg来做. 二.ffmpeg实际操作 首先把需要添加水印的视频文件,上传 ...

  4. JasperReport报表导出踩坑实录

    写在最前面 翻了翻博客,因为太忙,已经好久没认真总结过了. 正好趁着今天老婆出门团建的机会,记录下最近这段时间遇到的大坑-JasperReport. 六月份的时候写过一篇利用poi文件导入导出的小De ...

  5. HashMap踩坑实录——谁动了我的奶酪

    说到HashMap,hashCode 和 equals ,想必绝大多数人都不会陌生,然而你真的了解这它们的机制么?本文将通过一个简单的Demo还原我自己前不久在 HashMap 上导致的线上问题,看看 ...

  6. (最新)VS2015安装以及卸载过程——踩坑实录

    前言 Visual Studio (简称VS)是微软公司旗下最重要的软件集成开发工具产品.是目前最流行的 Windows 平台应用程序开发环境,也是无数人学习编程的入门软件之一.Visual Stud ...

  7. Springboot+Mybatis+MySQL实例练习时踩坑记录

    最近刚开始学习后端,直接让上手学习Springboot+Mybatis+MySQL对CRUD的实例,虽然实例不难,但是上面的三个知识我都不懂,就有点为难我了 所以经常遇到一个点卡自己很久的情况,这里列 ...

  8. Angular2,Springboot,Zuul,Shiro跨域CORS请求踩坑实录

    前言:前后端分离,业务分离,网关路由等已经成为当下web application开发的流行趋势.前端以单页面路由为核心的框架为主体,可以单独部署在nodejs或nginx上.后端以springboot ...

  9. ffmpeg 踩坑实录 安装与视频切片(一)

    这段时间一直在做一个关于视频处理的项目.其中有一块需要切片相关功能.于是采用了ffmpeg来完成相关需求. 第一,ffmpeg的安装. 首先下载官方包,我这里用的是ffmpeg-release-64b ...

  10. windows安装rabbitmq踩坑实录

    最近学习springcloud消息总线需要用到rabbitmq,然后安装的时候踩了一些坑,记录如下: 首先安装rabbitmq之前需要先安装erlang,因为rabbitmq服务端使用erlang写的 ...

随机推荐

  1. [FAQ] iCloud 照片共享, 收到xx集团邀你xx, 拒绝 or 关闭 ?

    如果你收到邀请日历这是垃圾邮件和简单地选择"拒绝"选项,这个问题不会消失. 事实上,很可能增加,因为垃圾邮件发送者知道该帐户被激活.这同样适用于iCloud的照片共享. 对于iCl ...

  2. dotnet 读 WPF 源代码笔记 插入触摸设备的初始化获取设备信息

    在 WPF 触摸应用中,插入触摸设备,即可在应用里面使用上插入的触摸设备.在 WPF 使用触摸设备的触摸时,需要获取到触摸设备的信息,才能实现触摸 获取触摸设备插入 在 WPF 中,通过 Window ...

  3. 使用 @NoRepositoryBean 简化数据库访问

    在 Spring Data JPA 应用程序中管理跨多个存储库接口的数据库访问逻辑可能会变得乏味且容易出错.开发人员经常发现自己为常见查询和方法重复代码,从而导致维护挑战和代码冗余.幸运的是,Spri ...

  4. Lua 学习笔记(自用)

    Lua 学习笔记 1 语言基础 运行方式类似Python,可以直接在交互行运行,也可以通过解释器运行某个脚本.也可以在交互行运行某个lua脚本 dofile("hello.lua" ...

  5. 【Python基础】两个参数的for循环步长写法

    一个参数for循环步长写法 >>> for i in range(1,10000,1000):print(i) ... 1 1001 2001 3001 4001 5001 6001 ...

  6. WEB服务与NGINX(25)- LNMP架构-WEB集群部署phpmyadmin

    目录 1 LNMP架构-WEB集群部署phpmyadmin 1.1 WEB集群架构需求分析 1.2 WEB集群架构环境 1.3 部署mariadb 1.4 部署web服务器nginx 1.5 部署re ...

  7. Ubuntu虚拟机ROS的安装与使用

    ROS安装 直达链接 安装ROS2 使用鱼香ROS的一键安装: wget http://fishros.com/install -O fishros && bash fishros 进 ...

  8. 记一次Nacos漏洞的复现 --> 身份认证绕过漏洞(QVD-2023-6271)

    前记 端午前两天,遇到公司某客户的站点是Nacos,随后就是网上搜一波漏洞,搜到 QVD-2023-6271,故做以下记录 漏洞复现 漏洞描述 漏洞原理为开源服务管理平台 Nacos在默认配置下未对 ...

  9. java的synchronized有几种加锁方式

    在Java中,synchronized关键字提供了内置的支持来实现同步访问共享资源,以避免并发问题.synchronized主要有三种加锁方式: 1.同步实例方法 当一个实例方法被声明为synchro ...

  10. uni-app前端图表组件库,折线图横屏android失败的解决办法

    网址:https://www.ucharts.cn/v2/#/demo/index,需要登录,微信就可以 我在使用折现图时,业务需要把曲线图在点击全屏时横屏全屏显示.就做个全屏页面,点击后,把opti ...