2023年12月15日更改时间为, 09时59分00秒, 而后, 作者是shyの同学。
起始部分, 是在运用 java 语言来开展开发工作, 并且借助 maven 去进行项目管理之际, 我们常常会碰到一个令人头疼不已的状况, 那就是 jar 包存在冲突, 而这篇文章, 主要呢是给大伙们介绍了有关 jar 包冲突层面通常所采用的处理办法, 有需要的朋友们, 是能够参照一下的。
使用背景
构建工程期间的时候, 多方依赖自然会由此被不可避免地引入进来。jar包冲突所产生的结果, 大致能够划分成两类:
1.不同的版本, 在同一个jar包中出现了多个。应用择选的版本出现错误, 致使jvm在加载类时, 无法加载到所需的类, 或者加载到的是错误版本的类。
2.有不同的jar包, 其中出现了类路径一致的类, 同样的类出现在多个不同的依赖jar这当中, 因为jar加载具有先后顺序, 所以导致了JVM加载了错误版本的类。
maven - enforcer - plugin , 它能够在 maven 构建的时候, 将 jar 包冲突类似的问题, 以此那种显式的方式展现出来。
通过此插件去查验是不是存在由maven直接或者传递依赖所引发的jar包冲突, 于编译打包阶段能够让显式构建出现失败的情况。
准许创建一系列规则, 使之必须被遵守, 包含设定Java版本, 设定Maven版本, 禁止某些依赖, 统一jar包版本, 禁止SNAPSHOT快照等。maven - enforcer - plugin的enforce目标承担检查规则的职责, 它默认被绑定到生命周期的validate阶段。在规则被破坏之际, Maven就会报错。
除了标准的规则之外,还可以扩展该插件,编写自己的规则。
maven仲裁机制
相对于首个jar包冲突这一情况而言, maven给出了一套用于裁定依循哪个版本的仲裁机制, 存有以下原则。
1.按照依赖管理元素中指定的版本。此时下面两个原则无效。
2.路径最短原则
若不存在版本申明, 依据路径最短的那项原则, 也就是去挑选依赖树里最短的路径。
1)加载那个特定jar包的类加载器, 在jvm类加载器树结构里所处的层级, 是怎样的呢。
因为jvm有着双亲委派机制, 所以呈现出如此奇异的一幕: 层级越高的类加载器, 在面对那个加载路径之下的类时, 更靠前地去展开加载动作。
也就是说, 最先被加载的是bootstrap ClassLoader, 其次才是extension ClassLoader, 而最后加载的则是system ClassLoader。
2)文档系统当中, 文档的加载顺序是这样的, tomcat之类的容器, 其classLoader在获取加载路径之下的文档列表之际, 并不会进行排序, 而是依赖于底层的文档系统所返回的顺序, 一旦不同环境之间的文档系统并非一致, 那么就会出现这种情况, 有的环境不会有问题, 而有的环境则会产生冲突。
比如:测试和线上环境不一致导致的问题。
最先声明原则
要是路径的长短并不存在不同的情况, 那么在进行仲裁操作的时候, 就按照第一声明这个原则来开展, 也就是去挑选pom文件里最初表述的版本。
使用说明

在应用模块的pom.xml文件里, 此文件是最终打包运行时的文件, 引入maven - enforcer - plugin依赖, 其模板能够参照下方的通用模板。
运行命令 mvn validate 用以进行校验, 而编译命令会触发校验, 打包命令同样也会触发校验。
将校验关闭, 去执行命令, 加入 -Denforcer.skip=true, 像这样, 比如: mvn clean validate -Denforcer.skip=true。
通用模板
在有着parent pom的多模块应用里头, 于应用模块的pom.xml当中去引入依赖。
org.apache.maven.plugins maven-enforcer-plugin 1.4.1 enforce enforce validate enforce-ban-duplicate-classes enforce javax.* org.junit.* net.sf.cglib.* org.apache.commons.logging.* org.springframework.remoting.rmi.RmiInvocationHandler true false org.codehaus.mojo extra-enforcer-rules 1.0-beta-6
更多详细规则说明参见官网:maven官网
冲突解决
第一种jar冲突报错信息:
进行测试运行, 运行的是maven validate, 之后出现了enforcer报错信息, 则具体内容如下:
Dependency convergence error for org.slf4j:slf4j-api:1.7.12 paths to dependency are:
+-com.cainiao:boyan-native-test:0.0.1-SNAPSHOT
+-com.aliyun.opensearch:aliyun-sdk-opensearch:3.1.3
+-org.slf4j:slf4j-api:1.7.12
and
+-com.cainiao:boyan-native-test:0.0.1-SNAPSHOT
+-org.springframework.boot:spring-boot-starter:2.2.5.RELEASE
+-org.springframework.boot:spring-boot-starter-logging:2.2.5.RELEASE
+-ch.qos.logback:logback-classic:1.2.3
+-org.slf4j:slf4j-api:1.7.12
and
+-com.cainiao:boyan-native-test:0.0.1-SNAPSHOT
+-org.springframework.boot:spring-boot-starter:2.2.5.RELEASE
+-org.springframework.boot:spring-boot-starter-logging:2.2.5.RELEASE
+-org.apache.logging.log4j:log4j-to-slf4j:2.12.1
+-org.slf4j:slf4j-api:1.7.25
and
+-com.cainiao:boyan-native-test:0.0.1-SNAPSHOT
+-org.springframework.boot:spring-boot-starter:2.2.5.RELEASE
+-org.springframework.boot:spring-boot-starter-logging:2.2.5.RELEASE
+-org.slf4j:jul-to-slf4j:1.7.30
+-org.slf4j:slf4j-api:1.7.30
能够瞧见, org.slf4j:slf4j-api的jar被引入了好些个, 而且版本并非相同, 并不一致。在这个时候, 这情况就要求要把确切不想要的jar予以排除。
借助maven helper插件进行排除时, 在pom.xml文件的Dependency Analyzer里, 会显示出所有的jar包冲突。
看到此图, 要是用鼠标右键去点击一下exclude, 这样便能达成排除的目的, 这和以手动方式去添加exclude的那种操作是具有同等效果的。
排除后依赖显示如下:
org.springframework.boot spring-boot-starter 2.2.5.RELEASE slf4j-api org.slf4j
第二种jar包冲突报错信息:
总结
在此这个关于jar包冲突常用解决办法的文章就讲述到这儿了, 更多有关jar包冲突解决方面的内容, 请查找脚本之家之前的文章, 或者持续浏览下面的相关文章, 期望大家往后多多支持脚本之家!