Maven中出现JAR包冲突如何解决

发布时间:2021-03-03 15:49:08 作者:Leah
来源:亿速云 阅读:115

本篇文章给大家分享的是有关出现Maven JAR包冲突如何解决,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

JAR冲突产生的原因

   Pom.xml
   /  \
  B    C
 / \   / \
 X  Y  X  M

在以上依赖关系中项目除了会引入B、C还会引入X、Y、M的依赖包,但是如果B依赖的X版本会1.0而C依赖的X版本为2.0时,那最后项目使用的到底是X的1.0版本还是2.0版本就无法确定了。这是就要看ClassLoader的加载顺序,假设ClassLoader先加载1.0版本那就不会加载2.0版本,反之同理

使用mvn -Dverbose dependency:tree排查冲突

[INFO] +- org.apache.tomcat:tomcat-servlet-api:jar:7.0.70:compile
[INFO] +- org.apache.tomcat:tomcat-jsp-api:jar:7.0.70:compile
[INFO] | +- org.apache.tomcat:tomcat-el-api:jar:7.0.70:compile
[INFO] | \- (org.apache.tomcat:tomcat-servlet-api:jar:7.0.70:compile - omitted for duplicate)
[INFO] +- net.sf.jasperreports:jasperreports:jar:5.6.0:compile
[INFO] | +- (commons-beanutils:commons-beanutils:jar:1.8.0:compile - omitted for conflict with 1.8.3)
[INFO] | +- commons-collections:commons-collections:jar:3.2.1:compile
[INFO] | +- commons-digester:commons-digester:jar:2.1:compile
[INFO] | | +- (commons-beanutils:commons-beanutils:jar:1.8.3:compile - omitted for duplicate)
[INFO] | | \- (commons-logging:commons-logging:jar:1.1.1:compile - omitted for duplicate)

递归依赖的关系列的算是比较清楚了,每行都是一个jar包,根据缩进可以看到依赖的关系

该命令可配合-Dincludes和-Dexcludes进行使用,只输出自己感兴趣/不感兴趣的JAR
参数格式为:[groupId]:[artifactId]:[type]:[version]
每个部分(冒号分割的部分)是支持*通配符的,如果要指定多个格式则可以用,分割,如:

mvn dependency:tree -Dincludes=javax.servlet,org.apache.*

解决冲突,使用exclusion标签将冲突的JAR排除

<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>dubbo</artifactId>
  <version>2.8.3.2</version>
  <exclusions>
    <exclusion>
      <artifactId>guava</artifactId>
      <groupId>com.google.guava</groupId>
    </exclusion>
    <exclusion>
      <artifactId>spring</artifactId>
      <groupId>org.springframework</groupId>
    </exclusion>  
  </exclusions>
</dependency>

解决了冲突后的树(解决冲突的策略是:就近原则,即离根近的依赖被采纳)

查看运行期类来源的JAR包

有时你以为解决了但是偏偏还是报类包冲突,典型症状是java.lang.ClassNotFoundException或Method不兼容等异常,这时你可以设置一个断点,在断点处通过下面这个工具类来查看Class所来源的JAR包

public class ClassLocationUtils {
  public static String where(final Class clazz) {
    if (clazz == null) {
      throw new IllegalArgumentException("null input: cls");
    }
    URL result = null;
    final String clazzAsResource = clazz.getName().replace('.', '/').concat(".class");
    final ProtectionDomain protectionDomain = clazz.getProtectionDomain();
    if (protectionDomain != null) {
      final CodeSource codeSource = protectionDomain.getCodeSource();
      if (codeSource != null) result = codeSource.getLocation();
      if (result != null) {
        if ("file".equals(result.getProtocol())) {
          try {
            if (result.toExternalForm().endsWith(".jar") || result.toExternalForm().endsWith(".zip")) {
              result = new URL("jar:".concat(result.toExternalForm()).concat("!/").concat(clazzAsResource));
            } else if (new File(result.getFile()).isDirectory()) {
              result = new URL(result, clazzAsResource);
            }
          } catch (MalformedURLException ignore) {

          }
        }
      }
    }
    if (result == null) {
      final ClassLoader clsLoader = clazz.getClassLoader();
      result = clsLoader != null ? clsLoader.getResource(clazzAsResource) : ClassLoader.getSystemResource(clazzAsResource);
    }
    return result.toString();
  }
}

然后随便写一个测试设置好断点,在执行到断点出使用ALT+F8动态执行代码,如

ClassLocationUtils.where(Logger.class)

以上就是出现Maven JAR包冲突如何解决,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注亿速云行业资讯频道。

推荐阅读:
  1. 如何解决Maven jar包冲突
  2. 如何使用Maven Helper解决Maven插件冲突

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

maven jar

上一篇:C语言中有哪些不受限制的字符串函数

下一篇:怎么在pycharm中新建一个Django项目

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》