Maven是什么?

Maven是常年流行于Java界的Java项目管理构建自动化综合工具。

Maven提供了开发人员构建一个完整的生命周期框架。开发团队可以自动完成项目的基础工具建设,Maven使用标准的目录结构和默认构建生命周期。Maven让开发人员的工作更轻松,同时创建报表,检查,构建和测试自动化设置。Maven简化和标准化项目建设过程。处理编译,分配,文档,团队协作和其他任务的无缝连接。 Maven增加可重用性并负责建立相关的任务。

为什么要Maven?

  1. 依赖的管理:仅仅通过jar包的几个属性,就能确定唯一的jar包,在指定的文件pom.xml中,只要写入这些依赖属性,就会自动下载并管理jar包。
  2. 项目的构建:内置很多的插件与生命周期,支持多种任务,比如校验、编译、测试、打包、部署、发布..
  3. 项目的知识管理:管理项目相关的其他内容,比如开发者信息,版本等等。

Maven的依赖冲突问题

在日常开发项目中经常遇到一种情况:A依赖于B和C,而B又依赖于X、Y,而C依赖于X、M。那么,查看A的依赖时,就会看到A依赖了B,C,X,Y,M。其中,X,Y,M是通过传递依赖引入的。




maven依赖树打印 maven 依赖树_apache


那么就会有个问题:B,C都依赖了X,如果B和C依赖的X版本不相同,那么A所引入的X版本会是B的那个还是C的那个?

答:跟Classloader的加载顺序有关。如果Classloader先加载了B的X依赖,那就不会加载C的X依赖了。

又会有个问题:如果A希望引入的是C里面的那个X依赖,该怎么办?答案在下面。

mvn dependency:tree

使用mvn dependency:tree能够看出项目中几乎所有的依赖,包括传递依赖。而且会以层级树方式的方式显示出来,非常直观。下面就是一个mvn dependency:tree的例子。

[INFO] --- maven-dependency-plugin:2.1:tree (default-cli) @ euler-foundation ---
[INFO] com.hsit:euler-foundation:jar:0.9.0.1-SNAPSHOT
[INFO] +- com.rop:rop:jar:1.0.1:compile
[INFO] | +- org.slf4j:slf4j-api:jar:1.7.5:compile
[INFO] | +- org.slf4j:slf4j-log4j12:jar:1.7.5:compile
[INFO] | +- log4j:log4j:jar:1.2.16:compile
[INFO] | +- commons-lang:commons-lang:jar:2.6:compile
[INFO] | +- commons-codec:commons-codec:jar:1.6:compile
[INFO] | +- javax.validation:validation-api:jar:1.0.0.GA:compile
[INFO] | +- org.hibernate:hibernate-validator:jar:4.2.0.Final:compile
[INFO] | +- org.codehaus.jackson:jackson-core-asl:jar:1.9.5:compile
[INFO] | +- org.codehaus.jackson:jackson-mapper-asl:jar:1.9.5:compile
[INFO] | +- org.codehaus.jackson:jackson-jaxrs:jar:1.9.5:compile
[INFO] | +- org.codehaus.jackson:jackson-xc:jar:1.9.5:compile
[INFO] | - com.fasterxml.jackson.dataformat:jackson-dataformat-xml:jar:2.2.3:compile
[INFO] | +- com.fasterxml.jackson.core:jackson-core:jar:2.2.3:compile
[INFO] | +- com.fasterxml.jackson.core:jackson-annotations:jar:2.2.3:compile
[INFO] | +- com.fasterxml.jackson.core:jackson-databind:jar:2.2.3:compile
[INFO] | +- com.fasterxml.jackson.module:jackson-module-jaxb-annotations:jar:2.2.3:compile
[INFO] | - org.codehaus.woodstox:stax2-api:jar:3.1.1:compile
[INFO] | - javax.xml.stream:stax-api:jar:1.0-2:compile

为什么说几乎呢?因为有时候并没有显示出全部的依赖。这个时候就要使用-Dverbose参数了,这样就能输出全部的依赖,包括传递依赖。

有没有一种方式能只显示出我们关心的那些依赖,或者隐藏掉我们不关心的那些依赖?

答案是肯定的。用-Dincludes选项,-Dexcludes选项就也可以了。

用法:

-Dincludes=groupId:artifactId:version,其中,groupId:artifactId:version这些也可以不用全部写上。

例子:

mvn dependency:tree -Dverbose -Dincludes=org.apache.commons:commons-lang3

这样就会显示出项目中所有commons-lang3的依赖(包括传递依赖)。

[INFO] --- maven-dependency-plugin:2.1:tree (default-cli) @demo-test ---
[INFO] com.demo:demo-test:jar:1.0.2-SNAPSHOT
[INFO] +- org.apache.commons:commons-lang3:jar:3.5:compile
[INFO] - com.alipay-test:mytest:jar:1.0:compile
[INFO] | - (org.apache.commons:commons-lang3:jar:3.3.2:compile - omitted for conflict with 3.5)
[INFO] ------------------------------------------------------------------------

可以看到,项目中有个org.apache.commons:commons-lang3:jar:3.5的依赖,还有org.apache.commons:commons-lang3:jar:3.3.2的传递依赖。这两个版本依赖冲突了。

那么,如果我的项目只想要org.apache.commons:commons-lang3:jar:3.3.2版本的依赖,该怎么办?

答:使用maven的exclusion标签。

maven exclusion

从上面例子可以看到,org.apache.commons:commons-lang3:jar:3.3.2的传递依赖是通过com.alipay-test:mytest:jar:1.0的jar包引入的,那么,在引入com.alipay-test:mytest:jar:1.0的同时,使用exclusion排除其中的org.apache.commons:commons-lang3依赖即可。


maven依赖树打印 maven 依赖树_websocket的依赖jar包_02


再执行mvn dependency:tree -Dverbose -Dincludes=org.apache.commons:commons-lang3,就看不到3.3.2版本的依赖了。

[INFO] --- maven-dependency-plugin:2.1:tree (default-cli) @demo-test ---
[INFO] com.demo:demo-test:jar:1.0.2-SNAPSHOT
[INFO] +- org.apache.commons:commons-lang3:jar:3.5:compile
[INFO] - com.alipay-test:mytest:jar:1.0:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS