SpringbootV2.6整合Knife4j 3.0.3 问题记录

参考

https://juejin.cn/post/7249173717749940284

近期由于升级到springboot2.6X,所以服务端很多组件都需要重新导入以及解决依赖问题。
下面就是一个很经典的问题了,
springboot2.6与knife4j的整合。

版本对应

springboot2.6与knife4j 3.0.3

  • 两者路径匹配模式不同

由于Springfox使用的路径匹配是基于AntPathMatcher,而Spring Boot 2.6.X使用的是PathPatternMatcher,所以将MVC的路径匹配规则改成 AntPathMatcher。具体配置如下:

--- application.yml:
spring:mvc:pathmatch:#Springfox使用的路径匹配是基于AntPathMatcher的,而Spring Boot 2.6.X使用的是PathPatternMatcher 解决knife4j匹配boot2.6.7 boot版本过高的问题matching-strategy: ant_path_matcher-- 或者:application.properties:
spring.mvc.pathmatch.matching-strategy=ANT_PATH_MATCHER
  • springboot加载springfox过程中失败:
    第一个点很多文章都提到了,但是我主要遇到的是第二个点,表现在:
"org.springframework.web.servlet.mvc.condition.PatternsRequestCondition.getPatterns()" because "this.condition" is null

这时候你可以

新增一个配置类,注意配置类不能放到swagger的配置类下,测试无效。配置Bean可以放在启动类下或者重新新增一个配置Bean,代码如下:

package net.w2p.AppBase.fixBugs;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider;
import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;import java.lang.reflect.Field;
import java.util.List;
import java.util.stream.Collectors;/*** Springboot整合Knife4j问题修正*/
@Configuration
public class BeanPostProcessorConfig {@Beanpublic BeanPostProcessor springfoxHandlerProviderBeanPostProcessor() {return new BeanPostProcessor() {@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider) {customizeSpringfoxHandlerMappings(getHandlerMappings(bean));}return bean;}private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings) {List<T> copy = mappings.stream().filter(mapping -> mapping.getPatternParser() == null).collect(Collectors.toList());mappings.clear();mappings.addAll(copy);}@SuppressWarnings("unchecked")private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean) {try {Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");field.setAccessible(true);return (List<RequestMappingInfoHandlerMapping>) field.get(bean);} catch (IllegalArgumentException | IllegalAccessException e) {throw new IllegalStateException(e);}}};}}
  • 配置demo
package net.w2p.AppBase;import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import io.swagger.annotations.ApiOperation;
import net.w2p.WebExt.config.AppENV;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import springfox.documentation.RequestHandler;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;import javax.servlet.http.HttpSession;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;import static springfox.documentation.builders.PathSelectors.regex;/** @Api: 修饰整个类,描述Controller的作用* @ApiOperation: 描述一个类的一个方法,或者说一个接口* @ApiParam: 单个参数描述* @ApiModel: 用对象来接收参数* @ApiProperty: 用对象接收参数时,描述对象的一个字段* @ApiResponse: HTTP响应其中1个描述* @ApiResponses: HTTP响应整体描述* @ApiIgnore: 使用该注解忽略这个API* @ApiError :发生错误返回的信息* @ApiImplicitParam: 一个请求参数* @ApiImplicitParams: 多个请求参数*  doc.html*/@EnableSwagger2
@Configuration
@EnableKnife4jpublic class Swagger2Configuration implements WebMvcConfigurer {private String accessToken="token";private String title;private String description;private String version;private String termsOfServiceUrl;private String name;private String url;private String email;@Beanpublic Docket createRestApi() {boolean isEnableSwagger=true;if(!"test".equalsIgnoreCase(AppENV.getEnv())&&!"dev".equalsIgnoreCase(AppENV.getEnv())){isEnableSwagger=false;}if("dev".equalsIgnoreCase(AppENV.getEnv())){isEnableSwagger=true;}else{isEnableSwagger=false;}String scanPaths = "net.w2p.AppBase.controller.api;" +"net.w2p.AppBase.controller.common;" ;return new Docket(DocumentationType.SWAGGER_2).enable(isEnableSwagger).apiInfo(apiInfo())//                .enable(enableSwagger).directModelSubstitute(Timestamp.class, Long.class)//将Timestamp类型全部转为Long类型.directModelSubstitute(Date.class, Long.class)//将Date类型全部转为Long类型.forCodeGeneration(true).select().apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
//                .apis(RequestHandlerSelectors.any()).apis(basePackage(scanPaths))
//                .paths(PathSelectors.ant("/api/**"))
//                .paths(regex("^.*(?<!error)$")).paths(PathSelectors.any()).build()// 添加忽略类型.ignoredParameterTypes(HttpSession.class).securitySchemes(securitySchemes()).securityContexts(securityContexts());}private List<SecurityScheme> securitySchemes() {List<SecurityScheme> apiKeyList= new ArrayList();apiKeyList.add(new ApiKey("token", "token", "header"));return apiKeyList;}private List<SecurityContext> securityContexts() {List<SecurityContext> securityContexts=new ArrayList<>();securityContexts.add(SecurityContext.builder().securityReferences(defaultAuth()).forPaths(regex("^(?!auth).*$")).build());return securityContexts;}private List<SecurityReference> defaultAuth() {AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];authorizationScopes[0] = authorizationScope;List<SecurityReference> securityReferences = new ArrayList<>();securityReferences.add(new SecurityReference(accessToken, authorizationScopes));return securityReferences;}private ApiInfo apiInfo() {return new ApiInfoBuilder().title("api文档").description("综合前台网站").termsOfServiceUrl("http://www.baidu.com").contact(new Contact("freeLife","baidu.com","1000@qq.com")).version("2.9.2").build();}@Overridepublic void addResourceHandlers(ResourceHandlerRegistry registry) {System.out.println("================> add doc.html -url");registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
//        registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");}// 定义分隔符private static final String splitor = ";";/*** 声明基础包** @param basePackage 基础包路径* @return*/public static Predicate<RequestHandler> basePackage(final String basePackage) {return input -> declaringClass(input).transform(handlerPackage(basePackage)).or(true);}/*** 校验基础包** @param basePackage 基础包路径* @return*/private static Function<Class<?>, Boolean> handlerPackage(final String basePackage) {return input -> {for (String strPackage : basePackage.split(splitor)) {boolean isMatch = input.getPackage().getName().startsWith(strPackage);if (isMatch) {return true;}}return false;};}/*** 检验基础包实例** @param requestHandler 请求处理类* @return*/@SuppressWarnings("deprecation")private static Optional<? extends Class<?>> declaringClass(RequestHandler requestHandler) {return Optional.fromNullable(requestHandler.declaringClass());}
}

运行结果

在这里插入图片描述
正常运行。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c++二叉树寒假特训题目(1)

大家好&#xff0c;我是周曦&#xff0c;今天给大家推荐一些二叉树题目。 题目 二叉树存储 这道题是道水题&#xff0c;找找规律ok&#xff0c;本人代码10行。 淘汰赛 这道题推荐使用桶数组 做比较合适&#xff08;就是有点绕&#xff09;。 二叉树深度 这题是一道深搜题&a…

eclipse使用google的Java代码格式

插件下载地址 1.下载eclipse的插件 2.下载的jar包放到eclipse安装目录的dropins文件夹 D:\install_package\STS\sts-4.10.0.RELEASE\dropins&#xff13;.重启后设置 eclipse - windows - preference - java - code style - formatter -

MySQL篇----第十二篇

系列文章目录 文章目录 系列文章目录前言一、可以使用多少列创建索引?二、NOW()和 CURRENT_DATE()有什么区别?三、什么是非标准字符串类型?四、什么是通用 SQL 函数?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转…

【蓝桥杯冲冲冲】Invasion of the Milkweed G

【蓝桥杯冲冲冲】Invasion of the Milkweed G 蓝桥杯备赛 | 洛谷做题打卡day30 文章目录 蓝桥杯备赛 | 洛谷做题打卡day30[USACO09OCT] Invasion of the Milkweed G题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 题解代码我的一些话 [USACO09OCT] Invasion of the Mi…

linux centos 安装teleport

效果 安装 1.创建目录 mkdir -p /opt/teleport/data cd /opt/teleport/2.下载解压文件 wget https://tp4a.com/static/download/teleport-server-linux-x64-3.6.4-b3.tar.gz tar -xvf teleport-server-linux-x64-3.6.4-b3.tar.gz3.安装 cd /opt/teleport/teleport-server-l…

Python学习路线 - Python高阶技巧 - 拓展

Python学习路线 - Python高阶技巧 - 拓展 闭包闭包注意事项 装饰器装饰器的一般写法(闭包写法)装饰器的语法糖写法 设计模式单例模式工厂模式 多线程进程、线程并行执行多线程编程threading模块 网络编程Socket客户端和服务端Socket服务端编程实现服务端并结合客户端进行测试 S…

D音等短视频为什么这么吸引人?长期沉迷刷D音的危害 彻底戒掉刷D音上瘾 占用大量时间 注意力分散 思维浅薄 焦虑、抑郁 干扰睡眠 视力疲劳

这是你吗&#xff1f; 人生最爽的事是&#xff1a;刷痘印。 人生最不爽的事是&#xff1a;刷完&#xff0c;什么也没有得到&#xff0c;事也没做。 吸引法则 1. 内容碎片化&#xff0c;符合快节奏时代需求 短视频的时长通常只有几秒到十几分钟&#xff0c;内容简短精悍&…

苹果macbook电脑删除数据恢复该怎么做?Mac电脑误删文件的恢复方法

苹果电脑删除数据恢复该怎么做&#xff1f;Mac电脑误删文件的恢复方法 如何在Mac上恢复误删除的文件&#xff1f;在日常使用Mac电脑时&#xff0c;无论是工作还是娱乐&#xff0c;我们都会创建和处理大量的文件。然而&#xff0c;有时候可能会不小心删除一些重要的文件&#x…

Spring Boot3,启动时间缩短 10 倍!

前面松哥写了一篇文章和大家聊了 Spring6 中引入的新玩意 AOT&#xff08;见Spring Boot3 新玩法&#xff0c;AOT 优化&#xff01;&#xff09;。 文章发出来之后&#xff0c;有小伙伴问松哥有没有做性能比较&#xff0c;老实说&#xff0c;这个给落下了&#xff0c;所以今天…

Linux的计划任务(crontab)环境变量问题解决

1、背景 新上了个python服务&#xff0c;里面有调用oracle&#xff0c;其中有个需求需要定时去调用&#xff0c;贪方便想用crontab&#xff0c;出现了环境变量问题&#xff0c;于是跟他杠上了&#xff0c;势必要解决它&#xff01; 2、现象 尽管我在计划任务里写全了脚本路径…

使用 KITTI数据集训练YOLOX

1. 现在KITTI集后&#xff0c;首先将数据集转换为COCO数据集格式。 kitti_vis.py import os from pathlib import Path import numpy as np import cv2def anno_vis(img, anno_list):for anno in anno_list:points np.array(anno[4:8], dtypenp.float32)cv2.rectangle(img, (…

疯狂的2023年已过,聊聊我对大模型微调技术几点实践思考

大家好&#xff0c;今天聊聊我对大模型微调技术几点实践看法&#xff0c;喜欢记得收藏、关注、点赞。 更多技术交流&#xff0c;资料&#xff0c;文末加入我们技术群获取。 为什么要对大模型进行微调&#xff08;Fine-tuning&#xff09; 与其说对 LLM 大模型进行微调&#xf…

周期股是什么意思?包括哪些行业?

周期股是什么意思&#xff1f; 所谓的经济周期&#xff0c;又称商业周期或商业循环&#xff0c;是指经济运行中周期性出现的经济扩张与经济紧缩交替更迭&#xff0c;循环往复的一种现象。经济周期是由低迷、复苏、高潮、和衰落构成的&#xff0c;周而复始就形成了所谓的经济景…

HDFS架构 之 服务视图

1 、简介 为实现以上特性,HDFS包含的各个服务模块都是经过精心设计的,HDFS的服务视图如图。 HDFS的服务视图包含三大部分:核心服务、公共服务和拓展服务。 2、 核心服务 1)Namenode。HDFS系统采用中心化设计,即Master/Slave架构。这里的Namenode即是Master,主要作用是管…

影响2024年Web3赛道的三大事件

文章来源Techub News&#xff0c;搜Tehub News下载查看更多Web3资讯。 比特币ETF 2023年12月29日&#xff0c;路透社发布重要消息称&#xff0c;美国证券交易委员会&#xff08;SEC&#xff09;可能会在美国时间的1月2日或1月3日通知申请者他们是否获得了推出现货比特币ETF&a…

momentJs推导日历组件

实现效果: 代码&#xff1a; 引入momentjs然后封装两个函数构建出基本数据结构 import moment from moment;// 某月有多少天 export const getEndDay (m) > m.daysInMonth();/*** description 获取本月空值数据* param { Date } year { } 年度* param { Number } month …

vue3 之 组合式API—computed

computed计算属性函数 计算属性基本思想和Vue2的完全一致&#xff0c;组合式API下的计算属性只是修改了写法 核心步骤&#xff1a; 导入computed函数执行函数 在回调参数中return基于响应式数据做计算的值&#xff0c;用变量接收 vue <script setup> // 1.导入compute…

java中String类常用API

前言&#xff1a;在学习java的String类的时候&#xff0c;有很多的API需要了解&#xff0c;下面我将举出其中在新手学习时使用频率较大的几个API。 先大体看一下有哪几个&#xff1a;&#xff08;如图&#xff09; 目录 1.equals&#xff08;&#xff09;和 equalsIgnoreCase&…

一步步建立一个C#项目(连续读取S7-1200PLC数据)

这篇博客作为C#的基础系列,和大家分享如何一步步建立一个C#项目完成对S7-1200PLC数据的连续读取。首先创建一个窗体应用。 1、窗体应用 2、配置存储位置 3、选择框架 拖拽一个Button,可以选择视图菜单---工具箱 4、工具箱 拖拽Lable控件和TextBook控件 5、拖拽控件 接下来…

RAPTOR:树组织检索的递归抽象处理

RAPTOR: RECURSIVE ABSTRACTIVE PROCESSING FOR TREE-ORGANIZED RETRIEVAL Title&#xff1a;树组织检索的递归抽象处理 https://arxiv.org/pdf/2401.18059.pdf 摘要 检索增强语言模型可以更好的融入长尾问题&#xff0c;但是现有的方法只检索短的连续块&#xff0c;限制了整…