使用Maven检测依赖冲突

14

我有一个使用maven构建的Java应用程序,它引入了许多库。该应用程序在一个git库中(具有自己的maven构建),每个库都在其自己的git库中(具有自己的maven构建)。此外,应用程序和一些库都依赖于guava。

应用程序的pom.xml文件指定了guava版本为19.0:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>19.0</version>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
    </dependency>
</dependencies>

该应用程序还导入了另一个名为library1的库。 library1 也依赖于 guava。但是 library1 的 pom.xml 指定了 guava 的一个较新版本:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>23.0</version>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
    </dependency>
</dependencies>

应用程序构建时,Maven选择了在应用程序级别指定的Guava版本。但是这导致Library1失败,因为它期望使用更新的Guava版本。

如果我们使用的是Gradle并尝试指定这个Guava版本组合,我相信Gradle会导致构建失败,这可能是正确的做法。

考虑到我们可能会有POM.xml文件存在这样的版本差异,是否有一种方法可以设置Maven,以便它会注意到这种差异并且要么失败构建,要么显示关于问题的非常突出的警告?

2个回答

18

为了检测所有的传递依赖项,您可以使用 maven-dependency-plugin

mvn dependency:tree -Dverbose

它将展示您的项目的直接和传递依赖关系。 -Dverbose选项显示冲突。

[INFO] [dependency:tree]
[INFO] org.apache.maven.plugins:maven-dependency-plugin:maven-plugin:2.0-alpha-5-SNAPSHOT
[INFO] +- org.apache.maven.reporting:maven-reporting-impl:jar:2.0.4:compile
[INFO] |  \- commons-validator:commons-validator:jar:1.2.0:compile
[INFO] |     \- commons-digester:commons-digester:jar:1.6:compile
[INFO] |        \- (commons-collections:commons-collections:jar:2.1:compile - omitted for conflict with 2.0)
[INFO] \- org.apache.maven.doxia:doxia-site-renderer:jar:1.0-alpha-8:compile
[INFO]    \- org.codehaus.plexus:plexus-velocity:jar:1.1.3:compile
[INFO]       \- commons-collections:commons-collections:jar:2.0:compile

对于选择同一库的不同版本:

依赖冲突解决 - 确定遇到多个依赖版本时将选择哪个构件版本。Maven 选择“最近定义”的版本,也就是说,它使用最靠近项目依赖树中的依赖版本。您可以通过在项目的 POM 中显式声明来保证一个版本。请注意,如果两个依赖版本在依赖树中处于相同深度,则第一个声明将获胜。

“最近定义”意味着使用的版本将是离您的项目依赖树最近的版本。例如,如果 A、B 和 C 的依赖关系定义为 A-> B -> C -> D 2.0 和 A-> E -> D 1.0,则在构建 A 时将使用 D 1.0,因为通过 E 到达 D 的路径更短。您可以在 A 中显式添加对 D 2.0 的依赖项以强制使用 D 2.0。

因此,如果你的某个库与 guava 的其他版本不兼容,那么说明你的依赖关系不兼容。必须更新依赖关系以适应新版本。


6
[信息] 自 maven-dependency-plugin 3.0 版本起不再支持冗长输出。 - Nic

17

你可以在Maven中设置一个dependencyConvergence执行规则。该规则要求依赖版本号收敛。

如果一个项目有两个依赖项A和B,它们都依赖于同一个artifact C,如果A依赖于与B不同的C版本,则此规则将使构建失败。

以下方式可添加此规则。

<project>
  ...
  <build>
    <plugins>
      ...
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-enforcer-plugin</artifactId>
        <version>3.0.0-M2</version>
        <executions>
          <execution>
            <id>enforce</id>
            <configuration>
              <rules>
                <dependencyConvergence/>
              </rules>
            </configuration>
            <goals>
              <goal>enforce</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      ...
    </plugins>
  </build>
  ...
</project>

更多细节可以在这里找到。


这导致我的构建失败,并出现了一条规则的消息,但在我看来似乎与此无关:[WARNING] Rule 3: org.apache.maven.plugins.enforcer.RequirePluginVersions failed with message: Some plugins are missing valid versions:(LATEST RELEASE SNAPSHOT are not allowed ) - Ole V.V.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接