SpringBoot版本升级引起的FileNotFoundException——WebMvcConfigurerAdapter.class

news2024/11/18 8:15:17

缘起

最近公司项目要求JDK从8升到17,SpringBoot版本从2.x升级到3.x,期间遇到了一个诡异的FileNotFoundException异常,日志如下(敏感信息使用xxx脱敏)

org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [com.xxx.xxx.OperationAnalysisApplication]
	at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:179)
	at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:397)
	at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:283)
	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:344)
	at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:115)
	at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:745)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:565)
	at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:730)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:432)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:308)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1291)
	at com.xxx.xxx.OperationAnalysisApplication.main(OperationAnalysisApplication.java:34)
Caused by: java.io.FileNotFoundException: class path resource [org/springframework/web/servlet/config/annotation/WebMvcConfigurerAdapter.class] cannot be opened because it does not exist
	at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:211)
	at org.springframework.core.type.classreading.SimpleMetadataReader.getClassReader(SimpleMetadataReader.java:54)
	at org.springframework.core.type.classreading.SimpleMetadataReader.<init>(SimpleMetadataReader.java:48)
	at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:103)
	at org.springframework.boot.type.classreading.ConcurrentReferenceCachingMetadataReaderFactory.createMetadataReader(ConcurrentReferenceCachingMetadataReaderFactory.java:86)
	at org.springframework.boot.type.classreading.ConcurrentReferenceCachingMetadataReaderFactory.getMetadataReader(ConcurrentReferenceCachingMetadataReaderFactory.java:73)
	at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:81)
	at org.springframework.context.annotation.ConfigurationClassParser.asSourceClass(ConfigurationClassParser.java:611)
	at org.springframework.context.annotation.ConfigurationClassParser$SourceClass.getSuperClass(ConfigurationClassParser.java:924)
	at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:335)
	at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:244)
	at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:189)
	at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:298)
	at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:244)
	at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:197)
	at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:165)
	... 13 common frames omitted

SpringBoot3.x已经删除了类WebMvcConfigurerAdapter,建议实现接口WebMvcConfigurer

过程

1. 查找当前项目中使用WebMvcConfigurerAdapter的地方

这个报错日志明显没有提示出哪个类有问题,先排除当前项目自己写的代码有没有这个类,于是在IDEA中使用全局查找来查找使用WebMvcConfigurerAdapter的地方,发现都被WebMvcConfigurer接口替代了,看来并不是自己写的代码里面的,二是某个Jar中的,这大概就是没有显示因为哪个类继承了WebMvcConfigurerAdapter导致异常的原因吧

2. 查找哪个Jar中引用了这个类

下个断点看看

这TM和大海捞针没区别啊,这项目光依赖自己的包就几十个,大部分都是公司内部包,我都没有源码,这可怎么找啊,只能去报异常的地方碰碰运气了。我找到了报异常的地方:
日志显示在这

at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:211)

源码如下:

public InputStream getInputStream() throws IOException {
   InputStream is;
    if (this.clazz != null) {
        is = this.clazz.getResourceAsStream(this.path);
    } else if (this.classLoader != null) {
        is = this.classLoader.getResourceAsStream(this.absolutePath);
    } else {
        is = ClassLoader.getSystemResourceAsStream(this.absolutePath);
    }

    if (is == null) {
        throw new FileNotFoundException(this.getDescription() + " cannot be opened because it does not exist");
    } else {
        return is;
    }
}

报异常的地方很明显了,就是这

 if (is == null) {
     throw new FileNotFoundException(this.getDescription() + " cannot be opened because it does not exist");
 }

在这里下断点,启动项目,发现这个类里this.clazz是null,this.classLoader不是null,感觉这个classloader应该就是加载某个类的时候发现它的父类是WebMvcConfigurerAdapter,去加载WebMvcConfigurerAdapter找不到才报错的。就去这个classloader里面翻找了一下,感觉最有价值的就是里面的classes属性了,如下:
在这里插入图片描述

当前实例中的classes中找找

里面居然已经加载了5285个类,一个一个的看显然不行,于是在classes上右键,然后选择评估表达式,想着这个classes是个ArrayList,使用classes.stream().filter()筛选一下加载的类里面是否有父类是WebMvcConfigurerAdapter的,找到了不久知道是哪个有问题了么。写好筛选条件后执行,报错如下:
在这里插入图片描述
这…大概是JDK里面很多类还没加载导致的吧,看来这条行不通了。于是考虑这个classesArrayList类型,有序列表啊,其中最后一个元素有没有可能是当前继承了WebMvcConfigurerAdapter的类么?于是使用评估表达式获取了最后一个元素,很遗憾,是个idea的类:
在这里插入图片描述
梦想再一次破灭了。

是不是当前类加载器能提供点什么信息

想着是不是当前类加载器能看到当前在加载哪个类或者哪个类的加载引起了当前类的加载啊?很遗憾,classloader根本没有这信息,只有当前类加载器正在加载的这个类WebMvcConfigurerAdapter

看看谁触发了当前类加载

很遗憾,上面的方法都没找到很有用的信息,于是想着,看看谁调用了当前方法,也就是说谁触发了加载WebMvcConfigurerAdapter这个类的动作,于是顺着调用栈:
在这里插入图片描述
一直往回找,终于,在下面这个地方找到了:
在这里插入图片描述
这里点开resource字段,直接定位到类:

import com.zhongan.data.analytics.interceptor.RequestDataInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class InterceptorConfig extends WebMvcConfigurerAdapter {
    public InterceptorConfig() {
    }

    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new RequestDataInterceptor()).addPathPatterns(new String[]{"/**"});
        super.addInterceptors(registry);
    }
}

就是这了。
Jar里面没法排掉某个特定的类,只能在当前项目中创建一个和这个类一模一样的类,代码改成自己想要的。因为Java中,某个类(同一个classloader+全限定名)已经被加载了,就不会再次被加载,项目中的类加载优先于Jar包中的,又都是同一个类加载器加载,所以会优先加载到项目中类,Jar中的则不会被加载了,曲线救国 我试了下似乎不行,待考证,暂时先加删除线,后续会回来看看怎么解决这个问题。

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

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

相关文章

安科瑞智能型BA系列电流传感器

安科瑞虞佳豪 壹捌柒陆壹伍玖玖零玖叁 选型

微信小程序——同一控件的点击与长按事件共存的解决方案

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

一份 GitHub star 过万的 1121 页图解算法让“他”成功杀进字节跳动

前两天收到读者喜报&#xff0c;说是进字节了&#xff0c;和他交流了一下他的学习心得&#xff0c;发现他看的资料也是我之前推荐过的算法进阶指南&#xff0c;这里推荐给大家&#xff0c;github star 可是过万哦&#xff01;质量非常高&#xff01; 这份算法笔记与其他的不同&…

使用andlua+写一个获取VSCode最新版本号的安卓软件

点击加号 选择Defalut模板 名称改为vscv 包名改为com.b.vscv 编辑main.lua require "import" import "android.app.*" import "android.os.*" import "android.widget.*" import "android.view.*" import "layout&qu…

微信小程序开发总结

架构分析 软件应用架构包括&#xff1a; 数据层、业务逻辑层、服务处、控制层、展示层、用户&#xff0c;小程序属于展示层&#xff0c;通常还需要其他层次提供支持 主体文件&#xff1a; app.js,app.json,app.wxss&#xff0c;前两者是必须存在再根目录下&#xff0c;app.wxs…

【网络云盘客户端】——上传文件的功能的实现

目录 上传文件功能的实现 uploadtask的设计 设置上传的槽函数 uploadFileAction接口 uploadFile接口 定时上传文件 进度条的设计 上传文件功能的实现 上传文件功能实现 1.双击 ”上传文件 “的 QListWidgetItem 或者 点击 “上传” 菜单项 都会弹出一个文件对话框 2.在文…

关于Java中的Lambda变量捕获

博主简介&#xff1a;想进大厂的打工人博主主页&#xff1a;xyk:所属专栏: JavaEE进阶 目录 一、Lambda表达式语法 二、Lambda中变量捕获 一、Lambda表达式语法 基本语法: (parameters) -> expression 或 (parameters) ->{ statements; } Lambda表达式由三部分组成&a…

嵌入式:QT Day4

一、手动完成服务器的实现&#xff0c;并注释具体步骤 源码&#xff1a; widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTcpServer> //服务器类 #include <QTcpSocket> //客户端类 #include <…

vue-echarts配置项详解

起因 最近接手了一个vue3项目&#xff0c;echarts用的是"vue-echarts": “^6.0.0”&#xff0c;每次查看文档的时候痛苦不已&#xff0c;找一个配置要花费大量时间&#xff0c;所以这篇文章&#xff0c;主要就是为了记录比较常见的一些配置。 主要会写三种图的配置…

libcomposite: Unknown symbol config_group_init (err 0)

加载libcomposite.ko 失败 问题描述 如图&#xff0c;在做USB OTG 设备模式的时候需要用到libcomposite.ko驱动&#xff0c;加载失败了。 原因&解决方法 有一个依赖叫configfs.ko的驱动没有安装。可以从内核代码的fs/configfs/configfs.ko中找到这个驱动。先加载confi…

Linux学习之自定义函数

函数是把一些重复使用的命令封装成一个集合&#xff0c;之后可以使用函数名调用。 定义函数的格式如下&#xff1a; function 函数名() {指令集&#xff08;若干条语句&#xff09; return n }要是直接在Shell中直接定义函数&#xff0c;那么直接在Shell中直接使用函数名 参数…

建筑工地为什么要做人员定位?解读技术背后的安全与效益

建筑工地是一个复杂而危险的环境&#xff0c;人员安全一直是行业亟待解决的难题。为了确保工人的安全&#xff0c;并提高工地的管理效率&#xff0c;越来越多的建筑工地开始采用人员定位技术。 对此&#xff0c;华安联大便和各位朋友一起深入探讨人员定位技术的优势和功能&…

C++(14):重载运算与类型转换

当运算符被用于类类型的对象时&#xff0c;允许我们为其指定新的含义&#xff1b;同时&#xff0c;也能自定义类类型之间的转换规则。和内置类型的转换一样&#xff0c;类类型转换隐式地将一种类型的对象转换成另一种我们所需类型的对象。 当运算符作用于类类型的运算对象时&a…

一、创建自己的docker python容器环境;支持新增python包并更新容器;离线打包、加载image

1、创建自己的docker python容器环境 参考&#xff1a;https://blog.csdn.net/weixin_42357472/article/details/118991485 首先写Dockfile&#xff0c;注意不要有txt等后缀 Dockfile # 使用 Python 3.9 镜像作为基础 FROM python:3.9# 设置工作目录 WORKDIR /app# 复制当前…

了解网络层

网络层 1. 概述2. 网络层提供的两种服务2.1 面向连接的虚电路服务2.2 无连接的数据报服务2.3 虚电路服务 VS 数据报服务 3. IPv4地址及其应用3.1 分类编址的IPv4地址3.1.1 A类地址3.1.2 B类地址3.1.3 C类地址 3.2 划分子网的IPv4地址3.3 无分类编址的IPv4地址3.4 IPv4地址的应用…

出海品牌整合营销指南:打造全球化成功的关键策略

随着全球化的不断深入&#xff0c;越来越多的企业开始将目光投向海外市场&#xff0c;希望在国际舞台上展现自己的实力和魅力。然而&#xff0c;出海市场的竞争激烈&#xff0c;如何在陌生的土地上建立起品牌影响力&#xff0c;成为摆在出海企业面前的一大难题。在这样的背景下…

TD1850多用表校准系统参考标准

参考标准 分类 标准名称 国家标准 GB/T 13978-2008 数字多用表 GB/T 15637-2012 数字多用表校准仪通用规范 计量法规 JJF 1075-2015 钳形电流表校准规范 JJF 1284-2011 交直流电表校验仪校准规范 JJF 1587-2016 数字多用表校准规范 JJG 124-2005 电流表、电压表、功率表及…

苍穹外卖day02项目日志

1. 描述清楚新增员工的实现流程 1.1需求分析与设计 参考产品原型&#xff0c;设计表和接口。 1.1.1设计表 看员工管理的产品原型&#xff1a; 有员工姓名、账号、手机号、账号状态、最后操作时间等。 注意&#xff0c;操作一栏不是字段&#xff0c;其中的启用禁用才是。 再…

沦为囚犯的“烟草女王”卢平的管理口诀:大胆设计,小心求证

沦为囚犯的“烟草女王”卢平的管理口诀&#xff1a; 大胆设计&#xff0c;小心求证 卢平是当初是湖南烟草界女强人 大致2003年听到了一句话 在管理知识稀缺的年代 当初听了有点小激动 趣讲大白话&#xff1a;管理口诀有意思 【趣讲信息科技239期】 ***************************…

面试了一个在字节工作2年的“大佬”,我蚌埠住了

昨天面试了一位在字节跳动工作2年多的开发&#xff0c;简历上写的工作截止时间是“至今”。特意问了一下&#xff0c;才知道实际是六月份已经不在职了。面试也就进行了十多分钟&#xff0c;但想跟大家分享一些站在选人的视角如何看待面试中的一些问题。 先说说面试 首先肯定是…