项目场景:
SpringBoot集成EasyExcel,在导入Excel进行解析处理时,执行到doReadSync()时报错,提示java.lang.IncompatibleClassChangeError或者net.sf.cglib.beans.beanMap
not found。本地却没有问题
问题描述:
报错日志
com.alibaba.excel.exception.ExcelAnalysisException: java.lang.IncompatibleClassChangeError: class net.sf.cglib.core.DebuggingClassWriter has interface org.objectweb.asm.ClassVisitor as super class at com.alibaba.excel.analysis.ExcelAnalyserImpl.analysis(ExcelAnalyserImpl.java:126) at com.alibaba.excel.ExcelReader.read(ExcelReader.java:182) at com.alibaba.excel.ExcelReader.read(ExcelReader.java:172) at com.alibaba.excel.read.builder.ExcelReaderSheetBuilder.doReadSync(ExcelReaderSheetBuilder.java:80) at com.pab.fb.comb.account.open.service.batch.service.impl.BatchOpenAcctServiceImpl.importExcel(BatchOpenAcctServiceImpl.java:179) at com.pab.fb.comb.account.open.controller.batch.BatchOpenAcctController.uploadFile(BatchOpenAcctController.java:54) at com.pab.fb.comb.account.open.controller.batch.BatchOpenAcctController$$FastClassBySpringCGLIB$$5e8ec8cb.invoke
错误代码
List allList = EasyExcel.read(new BufferedInputStream(file.getInputStream()), listener).autoCloseStream(true).head(BoaExcelModel.class).sheet(0).doReadSync();
问题排查:
1、首先怀疑的是jar包冲突的问题,结果在本地用idea使用插件Maven Helper查看没有jar冲突的问题,asm包正常。
Maven Helper可以在官网下载 Maven Helper - IntelliJ IDEs Plugin | Marketplace
2、此时怀疑测试环境的环境可能不一样,于是下载测试环境的项目war包,解压后没有查找到asm.jar,此时已经明了是没有引入asm.jar的问题造成的,但是本地环境为什么没有问题呢?继续排查代码中asm.jar的引用,发现引入代码如下:
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
<scope>provided</scope>
</dependency>
scope标签参数为provided,不参与打包,所以测试环境没有asm.jar,但是本地maven仓库可能已经存在asm.jar包,所以代码不会报错。
这个标签的主要作用有三个:
1、确定导入的jar包的有效区域。这里说的区域分别为:
a)主程序区域: src/main/java
b)测试程序区域:src/test/java
2、是否参与maven项目的打包:
项目要部署到服务器上,是需要先将项目打包的。然而,并不是你导入项目的所有Jar包都需要一同被打包,比如junit这个专门用来编写测试的包及其依赖,就没有必要一起打包进项目中。使用scope的不同取值就能告诉maven哪些jar包需要被一同打包,哪些不用。
标签的取值(只介绍主要的三种):
1、compile(默认)
导入的jar对主程序是否有效:有效
导入的jar对测试程序是否有效:有效
是否参与项目的打包:参与
例如:在maven项目中使用了sping等第三方的jar包,则需要一同打包再部署到服务器。
2、test
导入的jar对主程序是否有效:无效
导入的jar对测试程序是否有效:有效
是否参与项目的打包:参与
例如:junit包,只在开发中测试使用,并不需要打包到服务器。
注:在eclipse中,若的取值若为test,则在右侧目录中,包会显示为灰色。
3、provided
导入的jar对主程序是否有效:有效
导入的jar对测试程序是否有效:有效
是否参与项目打包:不参与
例如:servlet-api,tomcat服务器自带,会自动添加到你部署的项目中,你开发项目时要用吗,但是不需
要一起打包。
注意:
中的值不能随便乱写,需要合理的选择,否则程序可能会出现错误。比如说,如果在导入一些Tomcat服务器自带的依赖(如:servlet-api)时使用了compile这个取值,项目运行时就会产生错误,因为Tomcat自带这些依赖,而你还将自己额外加入的相同的依赖部署到Tomcat下,两者就会差生冲突。而若是你在导入一些Tomcat没有但程序运行时需要的依赖时,使用了test或者provided,也会出错,因为这些依赖将不会一起被打包部署到Tomcat下,运行时就将找不到这些依赖。
scope对依赖传递的影响
什么是依赖传递?
就是假设你有一个maven项目叫A,你在这个项目中添加了一个依赖,这个依赖是你的另一个maven项目B,你在这个被依赖的项目B中添加一些依赖,这些依赖也会自动地添加到A中,这就是依赖传递。简单来说就是你的依赖的依赖也会成为你的依赖。
标签的取值对依赖传递有什么影响呢?
这个影响就是,只有当依赖的scope标签被定义为compile时才会发生依赖传递,而定义为test或者provided都不会发生依赖传递。