【Maven笔记】Maven依赖分析及冲突解决
在项目开发过程中, 常会需要分析JAR包依赖的需要, 从而解决 JAR 冲突等问题
Maven 常见分析命令
查看全部JAR信息
# 列出项目的所有JAR包
mvn dependency:list
# 列出项目的所有JAR包依赖树
mvn dependency:tree
# 列出项目的所有JAR包依赖树, 仅显示指定JAR的节点
## 参数形式: [groupId]:[artifactId]:[type]:[version]
## 多个JAR包可用逗号分割
## 示例是分析org.slf4j相关JAR, 博主解决UDF与自编译HIVE环境冲突时使用的
mvn dependency:tree -Dverbose -Dincludes=org.slf4j:*
# 列出项目的所有JAR包依赖树, 排除指定JAR的节点
mvn dependency:tree -Dverbose -Dexcludes=org.slf4j:*
上述两个命令是查看JAR包较为常用的命令, 如下是进阶参数
-Dverbose
: 会把被忽略的JAR, 即相同JAR包的不同版本引入也列出来.
查看依赖使用分析
# -Dverbose: 会把声明且使用JAR包也显示出来
mvn dependency:analyze-only
命令主要分析如下情况的依赖使用情况
- 声明了并且使用了的依赖
- 没有声明但是使用了的依赖
- 声明了但是没有使用的依赖
分析多模块依赖信息
mvn dependency:analyze-duplicate
用于分析 <dependencies/>
和
<dependencyManagement/>
中重复声明的依赖,
两者区别见dependencyManagement与dependencies区别
列出所有的远程repositories
mvn dependency:list-repositories
清理本地repository
# 分析项目依赖, 然后删除本地缓存, 重新从远程进行下载
mvn dependency:purge-local-repository
# 跳过删除前下载动作
## 由于需要对全部依赖进行处理, 会首先下载直至全部依赖就绪, 再进行删除缓存
mvn dependency:purge-local-repository -DactTransitively=false
# 包含/排除指定依赖
mvn dependency:purge-local-repository -Dincludes=org.slf4j:slf4j-api,org.slf4j:log4j-over-slf4j
# 自定义清理
## -DmanualInclude: 可以清理不在本项目中的依赖, 不会重新解析依赖, 因为本项目不需要这些依赖.
## 这个对清理parent pom, 导入的pom, maven插件非常有用
mvn dependency:purge-local-repository -DmanualIncludes=org.apache:apache
如何解决冲突问题
利用scope使用阶段
scope
类型:
compile
: 默认情况, 表示为当前依赖参与项目的编译、测试和运行阶段,属于强依赖.打包之时,会达到包里去.test
: 该依赖仅参与测试相关的内容,包括测试用例的编译和执行,比如定性的Junit.runtime
: 该依赖仅参与运行周期中的使用.一般这种类库都是接口与实现相分离的类库,比如JDBC类库,在编译之时仅依赖相关的接口,在具体的运行之时,才需要具体的mysql、oracle等等数据的驱动程序.此类的驱动都是为runtime的类库.provided
: 该依赖在打包过程中,不需要打进去,这个由运行的环境来提供,比如tomcat或者基础类库等等,事实上,该依赖可以参与编译、测试和运行等周期,与compile
等同.区别在于打包阶段进行了exclude
操作.system
: 使用上与provided
相同,不同之处在于该依赖不从maven
仓库中提取,而是从本地文件系统中提取,其会参照systemPath
的属性进行提取依赖.import
: 这个是maven 2.0.9
版本后出的属性,import
只能在dependencyManagement
的中使用,能解决maven
单继承问题,import依赖关系实际上并不参与限制依赖关系的传递性.
该方法主要用于处理运行环境与包冲突, 而非包内部的JAR冲突
<!-- 仅用于测试阶段 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.6.1</version>
<scope>test</scope>
</dependency>
<!-- 不编译进包,利用hive运行环境的hive-exec -->
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>${hive.version}</version>
<scope>provided</scope>
</dependency>
利用 <exclusions/
>`
如下为 Hadoop 与 hive 的 org.slf4j
发生冲突会报错,
利用如下命令进行显式排除
注意: 博主利用
*
通配符进行排除失败, 读者可使用自行用依赖树进行分析是否奏效
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>1.2.1</version>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>3.2.1</version>
</dependency>
预防包与运行环境的冲突情况
如果在大公司, UDF包等运行的环境相对固定,
而且其大数据平台一般均为自编译的, 具备着较强限制,
如何设置从而预防包冲突可以采用 maven-enforcer-plugin
插件(官网链接).
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>3.0.0-M3</version>
<executions>
<execution>
<id>enforce-versions</id>
<goals>
<goal>enforce</goal>
</goals>
<configuration>
<rules>
<requireMavenVersion>
<version>3.6.1</version>
</requireMavenVersion>
<requireJavaVersion>
<version>1.8.0</version>
</requireJavaVersion>
<bannedDependencies>
<!--是否检查传递性依赖(间接依赖)-->
<searchTransitive>true</searchTransitive>
<excludes>
<exclude>com.google.guava:guava</exclude>
<exclude>org.slf4j:*</exclude>
</excludes>
<message>Prompt for error message</message>
</bannedDependencies>
</rules>
</configuration>
</execution>
</executions>
</plugin>
参考资料
【Maven笔记】Maven依赖分析及冲突解决
https://www.windism.cn/2209565849.html