Maven依赖冲突解决:深度解析与实战技巧

这是文章《Maven 依赖树 – 解决冲突》的第1部分(共3部分)。

Maven 依赖树在理解项目的依赖关系以及解决因依赖版本不同而产生的冲突方面非常有帮助。

如何获取项目的Maven依赖树

我们可以在终端中运行 mvn dependency:tree 命令来打印项目依赖树。对于我们的示例,我将使用 Mockito 教程项目。您可以从 GitHub 仓库下载该项目。我们只关注项目的依赖关系。pom.xml 中声明了以下项目依赖项。

<dependencies>
	<dependency>
		<groupId>org.junit.platform</groupId>
		<artifactId>junit-platform-runner</artifactId>
		<version>1.2.0</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>org.junit.jupiter</groupId>
		<artifactId>junit-jupiter-engine</artifactId>
		<version>5.2.0</version>
		<scope>test</scope>
	</dependency>
	<dependency>
		<groupId>org.mockito</groupId>
		<artifactId>mockito-junit-jupiter</artifactId>
		<version>2.19.0</version>
		<scope>test</scope>
	</dependency>
	<!-- TestNG Dependencies -->
	<dependency>
		<groupId>org.testng</groupId>
		<artifactId>testng</artifactId>
		<version>6.14.3</version>
		<scope>test</scope>
	</dependency>
</dependencies>

让我们看一下运行 mvn dependency:tree 命令时的输出结果。

$ mvn dependency:tree                                                              
[INFO] Scanning for projects...
[INFO] 
[INFO] -----------------------------
[INFO] Building Mockito-Examples 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ Mockito-Examples ---
[INFO] com.Olivia.mockito:Mockito-Examples:jar:1.0-SNAPSHOT
[INFO] +- org.junit.platform:junit-platform-runner:jar:1.2.0:test
[INFO] |  +- org.apiguardian:apiguardian-api:jar:1.0.0:test
[INFO] |  +- org.junit.platform:junit-platform-launcher:jar:1.2.0:test
[INFO] |  +- org.junit.platform:junit-platform-suite-api:jar:1.2.0:test
[INFO] |  |  \- org.junit.platform:junit-platform-commons:jar:1.2.0:test
[INFO] |  \- junit:junit:jar:4.12:test
[INFO] |     \- org.hamcrest:hamcrest-core:jar:1.3:test
[INFO] +- org.junit.jupiter:junit-jupiter-engine:jar:5.2.0:test
[INFO] |  +- org.junit.platform:junit-platform-engine:jar:1.2.0:test
[INFO] |  |  \- org.opentest4j:opentest4j:jar:1.1.0:test
[INFO] |  \- org.junit.jupiter:junit-jupiter-api:jar:5.2.0:test
[INFO] +- org.mockito:mockito-junit-jupiter:jar:2.19.0:test
[INFO] |  \- org.mockito:mockito-core:jar:2.19.0:test
[INFO] |     +- net.bytebuddy:byte-buddy:jar:1.8.10:test
[INFO] |     +- net.bytebuddy:byte-buddy-agent:jar:1.8.10:test
[INFO] |     \- org.objenesis:objenesis:jar:2.6:test
[INFO] \- org.testng:testng:jar:6.14.3:test
[INFO]    +- com.beust:jcommander:jar:1.72:test
[INFO]    \- org.apache-extras.beanshell:bsh:jar:2.0b6:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.871 s
[INFO] Finished at: 2019-12-13T12:24:11+05:30
[INFO] ------------------------------------------------------------------------
$

输出显示了用于运行此应用程序的所有 JAR 文件。输出显示了依赖的 groupIdartifactIdpackagingversionscope

从Maven项目的依赖中排除一个依赖项

如果您查看以上的依赖树输出,您会发现 JUnit 4 JAR 是作为 junit-platform-runner 的传递依赖而被引入的。如果您计划使用 JUnit 5 编写测试用例,最好将 JUnit 4 从依赖中排除,以避免任何冲突。我们可以使用 <exclusions> 标签从项目依赖中排除 JUnit 4 JAR。这个标签必须添加到负责引入它的依赖之中。

<dependency>
	<groupId>org.junit.platform</groupId>
	<artifactId>junit-platform-runner</artifactId>
	<version>1.2.0</version>
	<scope>test</scope>
	<exclusions>
		<exclusion>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
		</exclusion>
	</exclusions>
</dependency>

让我们再次运行依赖树命令。现在它不应该显示 JUnit 4 的 JAR 包。

Maven 依赖树

使用Maven依赖树详细模式解决冲突

这是文章《Maven 依赖树 – 解决冲突》的第2部分(共3部分)。

内容片段: 当我们构建一个Maven项目时,Maven会选择离项目更近的依赖版本。当你想要一个特定版本但Maven选择了其他版本时,可能会出现问题。我们可以使用mvn dependency:tree -Dverbose命令打印出依赖冲突,这有助于我们确定是否存在与JAR不兼容的问题。

$ mvn dependency:tree -Dverbose
[INFO] Scanning for projects...
[INFO] 
[INFO] -----------------------------
[INFO] Building Mockito-Examples 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ Mockito-Examples ---
[INFO] com.Olivia.mockito:Mockito-Examples:jar:1.0-SNAPSHOT
[INFO] +- org.junit.platform:junit-platform-runner:jar:1.2.0:test
[INFO] |  +- org.apiguardian:apiguardian-api:jar:1.0.0:test
[INFO] |  +- org.junit.platform:junit-platform-launcher:jar:1.2.0:test
[INFO] |  |  +- (org.apiguardian:apiguardian-api:jar:1.0.0:test - omitted for duplicate)
[INFO] |  |  \- (org.junit.platform:junit-platform-engine:jar:1.2.0:test - omitted for duplicate)
[INFO] |  \- org.junit.platform:junit-platform-suite-api:jar:1.2.0:test
[INFO] |     +- (org.apiguardian:apiguardian-api:jar:1.0.0:test - omitted for duplicate)
[INFO] |     \- org.junit.platform:junit-platform-commons:jar:1.2.0:test
[INFO] |        \- (org.apiguardian:apiguardian-api:jar:1.0.0:test - omitted for duplicate)
[INFO] +- org.junit.jupiter:junit-jupiter-engine:jar:5.2.0:test
[INFO] |  +- (org.apiguardian:apiguardian-api:jar:1.0.0:test - omitted for duplicate)
[INFO] |  +- org.junit.platform:junit-platform-engine:jar:1.2.0:test
[INFO] |  |  +- (org.apiguardian:apiguardian-api:jar:1.0.0:test - omitted for duplicate)
[INFO] |  |  +- (org.junit.platform:junit-platform-commons:jar:1.2.0:test - omitted for duplicate)
[INFO] |  |  \- org.opentest4j:opentest4j:jar:1.1.0:test
[INFO] |  \- org.junit.jupiter:junit-jupiter-api:jar:5.2.0:test
[INFO] |     +- (org.apiguardian:apiguardian-api:jar:1.0.0:test - omitted for duplicate)
[INFO] |     +- (org.opentest4j:opentest4j:jar:1.1.0:test - omitted for duplicate)
[INFO] |     \- (org.junit.platform:junit-platform-commons:jar:1.2.0:test - omitted for duplicate)
[INFO] +- org.mockito:mockito-junit-jupiter:jar:2.19.0:test
[INFO] |  +- org.mockito:mockito-core:jar:2.19.0:test
[INFO] |  |  +- net.bytebuddy:byte-buddy:jar:1.8.10:test
[INFO] |  |  +- net.bytebuddy:byte-buddy-agent:jar:1.8.10:test
[INFO] |  |  \- org.objenesis:objenesis:jar:2.6:test
[INFO] |  \- (org.junit.jupiter:junit-jupiter-api:jar:5.1.0:test - omitted for conflict with 5.2.0)
[INFO] \- org.testng:testng:jar:6.14.3:test
[INFO]    +- com.beust:jcommander:jar:1.72:test
[INFO]    \- org.apache-extras.beanshell:bsh:jar:2.0b6:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  1.018 s
[INFO] Finished at: 2019-12-13T12:58:07+05:30
[INFO] ------------------------------------------------------------------------
$

依赖行(org.junit.jupiter:junit-jupiter-api:jar:5.1.0:test - omitted for conflict with 5.2.0)告诉我们这个JAR版本已被替换为另一个版本。如果您想使用junit-jupiter-api的5.1.0版本,只需将其添加到项目的Maven依赖中。由于Maven使用“最近优先”策略来解决版本冲突,因此直接依赖始终会包含在项目中。

筛选Maven依赖树

如果Maven项目有很多依赖,找到特定的构件将变得困难。

– 包含

我们可以使用-Dincludes选项从输出中仅包含特定的依赖。过滤模式的语法是[groupId]:[artifactId]:[type]:[version]。每个模式段都是可选的,并支持完整和部分的*通配符。

$ mvn dependency:tree -Dverbose -Dincludes=org.junit.jupiter:junit-jupiter-api
[INFO] Scanning for projects...
[INFO] 
[INFO] -----------------------------
[INFO] Building Mockito-Examples 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ Mockito-Examples ---
[INFO] com.Olivia.mockito:Mockito-Examples:jar:1.0-SNAPSHOT
[INFO] +- org.junit.jupiter:junit-jupiter-engine:jar:5.2.0:test
[INFO] |  \- org.junit.jupiter:junit-jupiter-api:jar:5.2.0:test
[INFO] \- org.mockito:mockito-junit-jupiter:jar:2.19.0:test
[INFO]    \- (org.junit.jupiter:junit-jupiter-api:jar:5.1.0:test - omitted for conflict with 5.2.0)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.981 s
[INFO] Finished at: 2019-12-13T13:04:04+05:30
[INFO] ------------------------------------------------------------------------
$

– 排除

这是文章《Maven 依赖树 – 解决冲突》的第3部分(共3部分)。

此选项用于从依赖树输出中移除指定的依赖项。其模式与 -Dincludes 选项相同。我们可以使用逗号来指定要从依赖树中包含或排除的多个模式。

$ mvn dependency:tree -Dexcludes=org.junit.jupiter:junit-jupiter-api 
[INFO] Scanning for projects...
[INFO] 
[INFO] -----------------------------
[INFO] Building Mockito-Examples 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ Mockito-Examples ---
[INFO] com.Olivia.mockito:Mockito-Examples:jar:1.0-SNAPSHOT
[INFO] +- org.junit.platform:junit-platform-runner:jar:1.2.0:test
[INFO] |  +- org.apiguardian:apiguardian-api:jar:1.0.0:test
[INFO] |  +- org.junit.platform:junit-platform-launcher:jar:1.2.0:test
[INFO] |  \- org.junit.platform:junit-platform-suite-api:jar:1.2.0:test
[INFO] |     \- org.junit.platform:junit-platform-commons:jar:1.2.0:test
[INFO] +- org.junit.jupiter:junit-jupiter-engine:jar:5.2.0:test
[INFO] |  \- org.junit.platform:junit-platform-engine:jar:1.2.0:test
[INFO] |     \- org.opentest4j:opentest4j:jar:1.1.0:test
[INFO] +- org.mockito:mockito-junit-jupiter:jar:2.19.0:test
[INFO] |  \- org.mockito:mockito-core:jar:2.19.0:test
[INFO] |     +- net.bytebuddy:byte-buddy:jar:1.8.10:test
[INFO] |     +- net.bytebuddy:byte-buddy-agent:jar:1.8.10:test
[INFO] |     \- org.objenesis:objenesis:jar:2.6:test
[INFO] \- org.testng:testng:jar:6.14.3:test
[INFO]    +- com.beust:jcommander:jar:1.72:test
[INFO]    \- org.apache-extras.beanshell:bsh:jar:2.0b6:test
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.925 s
[INFO] Finished at: 2019-12-13T13:55:22+05:30
[INFO] ------------------------------------------------------------------------
$ 

在Eclipse IDE中查看Maven依赖树

在Eclipse的pom.xml文件中,“Dependency Hierarchy”(依赖层级)选项卡显示了项目的依赖树。此选项卡分为两个部分:左侧显示详细的输出内容,右侧显示已解析的依赖关系。我们可以使用“Filter”(筛选)选项来查找特定的依赖。

Eclipse Pom Dependency Hierarchy

进一步阅读:在Eclipse IDE中使用Maven

将依赖树保存到文件

我们可以使用 -DoutputFile 选项来指定保存依赖树输出的文件。

$ mvn dependency:tree -DoutputFile=dependency-tree.txt
[INFO] Scanning for projects...
[INFO] 
[INFO] -----------------------------
[INFO] Building Mockito-Examples 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ Mockito-Examples ---
[INFO] Wrote dependency tree to: /Users/scdev/Desktop/maven-examples/Mockito-Examples/dependency-tree.txt
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  0.862 s
[INFO] Finished at: 2019-12-13T15:27:51+05:30
[INFO] ------------------------------------------------------------------------
$
$ cat dependency-tree.txt 
com.Olivia.mockito:Mockito-Examples:jar:1.0-SNAPSHOT
+- org.junit.platform:junit-platform-runner:jar:1.2.0:test
|  +- org.apiguardian:apiguardian-api:jar:1.0.0:test
|  +- org.junit.platform:junit-platform-launcher:jar:1.2.0:test
|  \- org.junit.platform:junit-platform-suite-api:jar:1.2.0:test
|     \- org.junit.platform:junit-platform-commons:jar:1.2.0:test
+- org.junit.jupiter:junit-jupiter-engine:jar:5.2.0:test
|  +- org.junit.platform:junit-platform-engine:jar:1.2.0:test
|  |  \- org.opentest4j:opentest4j:jar:1.1.0:test
|  \- org.junit.jupiter:junit-jupiter-api:jar:5.2.0:test
+- org.mockito:mockito-junit-jupiter:jar:2.19.0:test
|  \- org.mockito:mockito-core:jar:2.19.0:test
|     +- net.bytebuddy:byte-buddy:jar:1.8.10:test
|     +- net.bytebuddy:byte-buddy-agent:jar:1.8.10:test
|     \- org.objenesis:objenesis:jar:2.6:test
\- org.testng:testng:jar:6.14.3:test
   +- com.beust:jcommander:jar:1.72:test
   \- org.apache-extras.beanshell:bsh:jar:2.0b6:test
$ 

参考文献

bannerAds