假设我有四个项目:
在这种情况下,如果我运行项目A,Maven将正确解析对D的依赖。如果我理解正确,Maven总是采用最短路径的依赖。由于D是A的直接依赖性,因此将使用它,而不是在B中指定的D。
但现在假设这个结构:
在这种情况下,解析D的路径具有相同的深度。发生的事情是Maven会发生冲突。我知道有可能告诉Maven他应该排除依赖关系。但我的问题是如何解决这类问题。我的意思是在现实世界的应用程序中,你有很多依赖,也可能有很多冲突。
最佳实践解决方案是排除内容还是其他可能的解决方案?当我突然得到ClassNotFound Exception时,我发现很难处理,因为某些版本已经改变,这导致Maven采取不同的依赖。知道这一事实的原因使得更容易猜测问题是依赖性冲突。
我正在使用maven 2.1-SNAPSHOT。
答案 0 :(得分:72)
解决这种情况的主要方法是在项目的根pom中包含<dependencyManagement>
部分,您可以在其中指定将使用哪个库的版本。
编辑:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>foo</groupId>
<artifactId>bar</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
</dependencyManagement>
现在无论哪个版本的库foo:bar是由依赖项请求的,版本1.2.3将始终用于此项目和所有子项目。
<强>参考:强>
答案 1 :(得分:24)
Maven可以在没有任何冲突的情况下处理这两种情况。当需要两个版本的传递依赖时,将存在冲突。您描述的ClassNotFoundException
来自应用程序(或依赖项)的结果,尝试使用实际使用的冲突依赖项版本中不可用的类。
有多种方法可以解决问题。
<dependencyManagement>
部分指定传递依赖项应使用的冲突依赖项的版本<exclusion>
答案 2 :(得分:16)
这基本上不是maven问题,而是java问题。 如果项目B和项目C需要两个不兼容的项目D版本,那么您不能在项目A中使用它们。
不幸的是,正如您所知,Maven解决这类冲突的方法是选择要排除哪些冲突。
使用mvn dependency:analyze
和mvn dependency:tree
有助于查找您遇到的冲突。
答案 3 :(得分:10)
您可以使用规则enforce在整个项目中Dependency Convergence保持一致的依赖关系。
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.3.1</version>
<executions>
<execution>
<id>enforce</id>
<configuration>
<rules>
<DependencyConvergence/>
</rules>
</configuration>
<goals>
<goal>enforce</goal>
</goals>
</execution>
</executions>
</plugin>
答案 4 :(得分:5)
一种可能的策略是为主项目指定要使用的D版本(最新版本f.g.)。但是,如果库D不向后兼容,则存在kukudas所述的问题 - 在项目中不可能同时使用这两个库。
在这种情况下,可能需要在旧版本中使用B或C,这样两者都将取决于D的兼容版本。