浅谈Maven包冲突的原理及解决方法

1.概述

Apache Maven ,是一个软件(特别是Java软件)项目管理及自动构建工具。在没有Maven的上古年代,项目中引入jar包需要手动下载一个个的去下载,但是随着代码数量的增加,引入的jar包数量自然会增加,随之而来的就是jar包冲突的问题了。

2.产生jar包冲突的原因

众所周知,一个项目中不能存在两个全限定类名一致的Class类,并且jar包的本质就是打包好的Class类文件,例如: 将 junit-jupiter-api-5.6.2.jar 文件解压后,

可以得到多个Class文件,所以项目中同样不能存在两个名称项目的jar包。

与此同时,jar包之间也会存在相互依赖,就拿这个 junit-jupiter-api-5.6.2.jar 举例: pom坐标为:

<dependency>
 <groupId>org.junit.jupiter</groupId>
 <artifactId>junit-jupiter-api</artifactId>
 <version>5.6.2</version>
 <scope>test</scope>
</dependency>

那么可以在maven中央仓库找到该jar包的详细信息,地址: https://repo1.maven.org/maven2/org/junit/jupiter/junit-jupiter-api/5.6.2/

打开.pom文件可以看到该jar包还引用了哪些其他jar包,如下图所示:

当然我们可以通过IDEAL及maven工具查看完整的依赖树:

或者将依赖树信息导出到本地:

 mvn dependency:tree > a.txt

如下图所示:

所以说,随着我们项目的逐渐庞大,所引入的jar包文件逐渐增多,产生包冲突的可能性也会越来越大,我们不可能都用肉眼去查找项目中的包冲突问题。当然我们可以通过一些工具插件帮助我们查找项目中的jar包冲突,比如说 Maven Helper

3.引入插件解决冲突

以这个项目为例:

依赖关系图如下:

我们知道,当两个jar包产生冲突时,取舍原则是谁离的项目近选择谁,所以spring-web最终会选择5.1.8版本的。从最终的启动命令中也可以看出:

"D:\software\IDEA IU\IntelliJ IDEA 2019.3\jbr\bin\java.exe" "-javaagent:D:\software\IDEA IU\IntelliJ IDEA 2019.3\lib\idea_rt.jar=50098:D:\software\IDEA IU\IntelliJ IDEA 2019.3\bin" -Dfile.encoding=UTF-8 -classpath D:\GitHub_Item\resolve-package-conflict\target\classes;
C:\Users\DELL\.m2\repository\org\springframework\spring-web\5.1.8.RELEASE\spring-web-5.1.8.RELEASE.jar;
C:\Users\DELL\.m2\repository\org\springframework\spring-beans\5.1.8.RELEASE\spring-beans-5.1.8.RELEASE.jar;
C:\Users\DELL\.m2\repository\org\springframework\spring-core\5.1.8.RELEASE\spring-core-5.1.8.RELEASE.jar;
C:\Users\DELL\.m2\repository\org\springframework\spring-jcl\5.1.8.RELEASE\spring-jcl-5.1.8.RELEASE.jar;
C:\Users\DELL\.m2\repository\com\github\hcsp\test-library-a\0.4\test-library-a-0.4.jar Main

使用Maven Helper插件分析:

根据自己的需要,选择要排除的版本:

插件就会帮我们在pom.xml文件中,排除掉产生冲突的引入:

点击 Reimport

按钮,就可以看到冲突已经解决了。

4.引深学习

4.1 <scope>test</scope><scope>compile</scope> 的区别?

对于test而言,表示该依赖只作用于测试类中,也就是src/main/test路径下,在其他路径中,编译器是不会引入该依赖的。对于compile则没有限制,在src/main/java于src/mian/test中均可用。

4.2 <scope>provided</scope> 表示什么?

举例说明:

 public static void main(String[] args) throws IOException {
  Workbook workbook = new HSSFWorkbook(new FileInputStream("C:\\Users\\DELL\\Desktop\\new.xlsx"));
 }

pom.xml中引入必要的依赖:

<dependency>
   <groupId>org.apache.poi</groupId>
   <artifactId>poi</artifactId>
   <version>4.1.2</version>
   <scope>provided</scope>
  </dependency>

但是在带点击允许的时候,就是会报出:

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/poi/hssf/usermodel/HSSFWorkbook
at Main.main(Main.java:10)
Caused by: java.lang.ClassNotFoundException: org.apache.poi.hssf.usermodel.HSSFWorkbook
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
... 1 more

类没有找到的问题,原因在于设置 <scope>provided</scope> 则表示该依赖只在编译时的CLASSPATH中,在运行时则不将该依赖加入CLASSPATH中。一半用于运行环境已经将CLASSPATH设置好,不需要额外添加的情况,比如Tomcat。

5.资源共享

1.《Maven实战》---下载地址:https://github.com/lxw420302/books/blob/master/java/Maven%E5%AE%9E%E6%88%98.pdf

到此这篇关于浅谈Maven包冲突的原理及解决方法的文章就介绍到这了,更多相关Maven包冲突内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Maven jar包冲突的解决方案

    现象 创建一个maven工程,引入spring-context包. <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.8.RELEASE</version> </dependency> 此时看左侧的lib,我们发现引入了一个坐标,多出了很多的jar包,这

  • maven解决包冲突方法详解

    Maven根据最近胜利策略(nearest wins strategy)的原则工作,同时解决依赖冲突,这意味着它在依赖树中找到更接近的版本,它将采用该版本并忽略其他版本.实际上Maven有点懒,所以每当它开始寻找依赖时,它就会从根目录开始遍历树,无论它先前找到哪个版本,它都会选择它并从它们返回而不进一步.如果它进一步寻找依赖版本,可能会有机找到一些更新的版本,但它从第一个发现的版本那里返回,并采用旧版本并用它来解决依赖关系. 可以用下面的命令显示依赖树: mvn dependency:tree

  • maven 隐式依赖引起的包冲突解决办法

    包冲突 1.使用maven管理项目时可能会遇到包冲突的情况比如:log4j-over-slf4j.jar 和 slf4j-log4j12.jar这两个包同时一起运行时就会有问题. 2.这种冲突可能是显式依赖导致,也可能是隐式依赖导致. 显式依赖,直接可以从pom.xml文件的<dependency>中看到两个冲突包的引用. 隐式依赖,在pom.xml的<dependency>无法看到冲突的包,而是由<dependency>引入的包间接引入的. 解决 先确认哪些依赖间接引

  • idea中解决maven包冲突的问题(maven helper)

    日常开发中经常会遇到xxx.class 找不到的异常,但是这个类确实存在我们的项目中,就会感觉很离奇,其实这就是包冲突的问题 冲突问题 比如项目中引用了两个 fastjson.jar的版本,分别为 fastjson:1.2.28 fastjson:1.2.3 我们用到了1.2.28中的某个类, 比如 A类,在版本更新中 1.2.3版本去掉了这个类,然而我们项目中maven 却把1.2.3的 jar 打包进去了,那我们就会报异常,不存在这个 class,但是我们调错误的时候却发现这个类存在,那我们

  • 浅谈Maven包冲突的原理及解决方法

    1.概述 Apache Maven ,是一个软件(特别是Java软件)项目管理及自动构建工具.在没有Maven的上古年代,项目中引入jar包需要手动下载一个个的去下载,但是随着代码数量的增加,引入的jar包数量自然会增加,随之而来的就是jar包冲突的问题了. 2.产生jar包冲突的原因 众所周知,一个项目中不能存在两个全限定类名一致的Class类,并且jar包的本质就是打包好的Class类文件,例如: 将 junit-jupiter-api-5.6.2.jar 文件解压后, 可以得到多个Clas

  • 浅谈jQuery绑定事件会叠加的解决方法和心得总结

    关于jQuery的学习中我忽略了一个取消绑定事件.unbind()的使用,也不知道绑定事件会累加的情况,结果因为这个原因,让我在项目上栽了坑.只能说自己还太年轻,需要学习掌握的知识还有很多. 我遇到的问题 我在项目中遇到的状况,一个评价页面,简单的来说就是左右两个表格,ajax分别动态加载学生姓名学号信息和不同科目对学生评价内容两部分,两边表格我都每行写了checkbox并对table tbody tr绑定click事件执行行选功能,起初我写的是静态页面html,行选功能完全没有问题,后来换成j

  • 浅谈laytpl 模板空值显示null的解决方法及简单的js表达式

    laytpl 模板语法 {{ d.field }} 输出一个普通字段,不转义html 官方的说明 但d.field 为空时会显示null laytpl 模板 空值显示null的解决方法 {{d.giftName}} 模板中当giftName为空是 页面上会显示 null 字符串 1可以在模板中直接使用三目表达式来判断字符串是否为空. 如下: {{!d.giftName?" ":d.giftName}} 2还有一种方法,用到一个 || 运算符 {{d.giftName||" &

  • 浅谈maven的jar包和war包区别 以及打包方法

    jar文件包括java普通类.资源文件和普通文件,在maven中即是打包src/main/java和src/main/resources资源文件夹下的所有文件.在打包的时候会自动生成MATA-INF文件夹,用于存储maven的pom信息和MANIFEST.MF文件.例如: war文件包含全部的web应用程序,即所有的java类,配置信息和jsp.js等静态资源.但是需要注意war引用war的时候会将应用war的资源全部拷贝到当前war的相同文件下,重名的文件会被替换.例如: war包依赖: <d

  • 浅谈Maven的安装及修改为阿里云下载依赖

    使用JAVA工程管理越来越多的jar包,担心导错了,多导了,漏导了怎么办? 换一个IDE项目后项目会不会出一堆BUG,看的头皮发麻? 自己写的代码放在别人的机器上运行会不会出问题? Maven的强大毋庸置疑,当使用Maven后以上这些都不是问题,但是配置maven是一件耐心的事情,基本步骤总结如下: 一.下载 http://maven.apache.org/download.cgi 也可以直接在eclipse工具中下载,点击eclipse菜单栏Help->Eclipse Marketplace搜

  • 浅谈Maven的build生命周期和常用plugin

    简介 Maven为我们封装了很多构建中非常有用的操作,我们只需要执行简单的几个mvn命令即可. 今天我们要讨论一下mvn命令之下的生命周期的构建. lifecycle和Phases 所谓lifecycle,可以理解为可以执行一组命令的集合,用来执行具体的某些操作. Maven默认有三种lifecycle:default,clean和site.default主要用来处理项目的开发,clean主要用来负责项目的清理,site主要用来生成项目的文档. lifecycle是由一个或者多个phase组成的

  • 浅谈Android串口通讯SerialPort原理

    目录 前言 一.名词解释 二.SerialPort的函数分析 三.SerialPort打开串口的流程 四.疑惑 五.总结 前言 通过前面这篇文章Android串口通讯SerialPort的使用详情已经基本掌握了串口的使用,那么不经想问自己,到底什么才是串口通讯呢?串口通讯(Serial Communication),设备与设备之间,通过输入线(RXD),输出线(TXD),地线(GND),按位进行传输数据的一种通讯方式.CPU 和串行设备间的编码转换器(转换器(converter)是指将一种信号转

  • 浅谈maven单元测试设置代理

    背景 环境需要设置代理才能够访问外部网络,如果只是运行java程序来访问网络,我们可以通过java -jar test.jar -DproxyHost=proxy_ip -DproxyPort=proxy_port,但如果是java的maven项目中,单元测试需要访问网络,只执行mvn test则会导致单元测试的代码无法访问网络. 解决 Maven单元测试,使用的是Surefire Maven插件.当Surefire插件fork JVM时,并不会继承所有的系统属性.因此我们可以通过命令行来如下设

  • 浅谈laravel aliases别名的原理

    在laravel发现有些类可以直接use 类名,就能使用了,例如use DB;就可以使用DB类了,问题是DB这个类并不在根命名空间,这里面实际就是用到了别名. 先通过如下例子来分析基本原理 建立如下文件upload.php,内容为 <?php namespace test\test2; class upload{ public function test(){ return 123; } } 2 建立文件index.php,内容为 <?php namespace b; require('upl

  • 浅谈Mybatis #和$区别以及原理

    总结: 1.#可以防止Sql 注入,它会将所有传入的参数作为一个字符串来处理. 2.$ 则将传入的参数拼接到Sql上去执行,一般用于表名和字段名参数,$ 所对应的参数应该由服务器端提供,前端可以用参数进行选择,避免 Sql 注入的风险 为什么? 为什么# 和 $ 的作用不同,Mybatis 对他们做了哪些惨无人道的处理,我们看一下下面的例子,并追踪一下源码总结. 示例代码: 创建一个 tb_class 表(具体字段不做解释). 创建一个 ClassDao.java 并使用注解的方式 ,table

随机推荐