Maven 包冲突导致 NoSuchMethodError

项目清况

项目中有两个包都引用了jackson 的包且都是不再更新的版本

javascript 复制代码
// jarA 包中引入 org.codehaus.jackson 包 1.8.4 版本
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-core-asl</artifactId>
    <version>1.8.4</version>
</dependency>
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.8.4</version>
</dependency>

//jar B 包中引入了 org.codehaus.jackson 包 1.9.13 版本
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-core-asl</artifactId>
    <version>1.9.13</version>
</dependency>
<dependency>
    <groupId>org.codehaus.jackson</groupId>
    <artifactId>jackson-mapper-asl</artifactId>
    <version>1.9.13</version>
</dependency>

//  org.codehaus.jackson  包最后在 2013 年的时候发生了组织变化(fastxml) ,且后续不再维护
// 如今正确使用jackson   应该引入以下的 3 个包:
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.17.1</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.17.1</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.17.1</version>
</dependency>

从上面包中看得出,项目有些年代感了(springmvc 3.x 的版本,打包成war 部署运行),本着能运行的情况下,绝不随意改动的原则,还是继续使用 org.codehaus.jackson 这个包

报错、异常

web 项目 能正常编译,运行时也正常启动,但执行到需要调用 org.codehaus.jackson 包中的某个方法时,产生运行异常:NoSuchMethodError:org.codehaus.jackson.map.ObjectMapper.setSerializationInclusion

找到报错处是 jarB 中的程序片段异常,找到对应代码中引用的包,定位后发现确实不存在这个方法,此时打开的是 1.8.4 的版本,(jarB 需要 1.9.13 版本的包)

处理冲突

找到问题了就好说,1.9与 1.8的版本应该上线兼容,则采用 1.9 的版本即可, 那么我们只需要在 jarA 中排除掉 1.8.4 的jackson 应该就能解决问题

xml 复制代码
<dependency>
    <groupId>org.china.xxxx</groupId>
    <artifactId>jarA</artifactId>
    <version>x.x.x</version>
    // 排除 ,jarA 中对低版本的引入
    <exclusion>
					<artifactId>jackson-core-asl</artifactId>
					<groupId>org.codehaus.jackson</groupId>
				</exclusion>
				<exclusion>
					<artifactId>jackson-mapper-asl</artifactId>
					<groupId>org.codehaus.jackson</groupId>
				</exclusion>
</dependency>

做了这个动作之后发现,项目中的已换成 1.9.13 版本

可以 使用 Maven Helper 工具来查看依赖冲突,exclude 包等

排除后充新编译项目启动运行,发现仍然

NoSuchMethodError:org.codehaus.jackson.map.ObjectMapper.setSerializationInclusion

进一步探究

  1. 编写单元测试 方法调用,发现单元测试没问题

📖 说明问题出在 Tomcat, 编译没问题说明包引入正常(idea 中包依赖显示正常,且跟踪代码也能找到正确的包) 问题应该出在 ClassLoad → 类加在上

  1. tomcat 启动项 增加 -XX:+TraceClassLoading -XX:+TraceClassUnloading tomcat 启动后发现,jackson 仍然加载 1.8.4 的版本
  1. 根据步骤 2 查看对应的目录发现,存在多个版本的包(但低版本的我应该排除掉了才对), 这个目录在 idea 项目的 target目录下 target/项目名称/WEB-INF/lib

结合了解到tomcat 加载 lib 目录下的包时,会按照顺序加在,且同样的包只会加在一次,所以,这里应该是优先加在了 1.8.4 所以后续引入的 1.9 就被忽略

那么问题来了-》 dependency 中 exclusion 排除了 低版本的包,是怎么又出现在 lib 中的,

发现问题

最后仔细观察 发现 jarA 是作为父项目,引入到当前项目中的

overlay 的资源会被覆盖到当前项目中,包括,WEB-INF 下的所有lib 这也是为什么在 lib 目录下仍然存在 1.8.4 版本的包. 需要在 overlay 中也将相应的包剔除

xml 复制代码
...
<plugin>
					<groupId>org.apache.maven.plugins</groupId>
					<artifactId>maven-war-plugin</artifactId>
					<version>2.2</version>
					<configuration>
						<overlays>
							<overlay>
								<groupId>com.unionman</groupId>
								<artifactId>unionmanframe</artifactId>
								<excludes>
									<exclude>**/jackson-core-asl-1.8.4.jar</exclude>
									<exclude>**/jackson-mapper-asl-1.8.4.jar</exclude>
								</excludes>
							</overlay>
						</overlays>
					</configuration>
	</plugin>
	...

最后再次启动,类正常加载 jackson-1.9.13 包

相关推荐
aloha_7892 小时前
从零记录搭建一个干净的mybatis环境
java·笔记·spring·spring cloud·maven·mybatis·springboot
尢词4 小时前
SpringMVC
java·spring·java-ee·tomcat·maven
wrx繁星点点4 小时前
享元模式:高效管理共享对象的设计模式
java·开发语言·spring·设计模式·maven·intellij-idea·享元模式
前 方6 小时前
若依入门案例
java·spring boot·maven
咕哧普拉啦6 小时前
乐尚代驾十订单支付seata、rabbitmq异步消息、redisson延迟队列
java·spring boot·mysql·spring·maven·乐尚代驾·java最新项目
不像程序员的程序媛8 小时前
mybatisgenerator生成mapper时报错
maven·mybatis
移民找老国8 小时前
加拿大移民新风向
java-ee·maven·phpstorm·visual studio code·nio
LUwantAC8 小时前
Java学习路线:Maven(三)继承关系
java·学习·maven
尘浮生12 小时前
Java项目实战II基于Spring Boot的问卷调查系统的设计与实现(开发文档+数据库+源码)
java·开发语言·数据库·spring boot·后端·maven·intellij-idea
弗拉唐14 小时前
SSM中maven
java·前端·maven