java - 为什么 Maven 包含相同依赖项的多个版本?

标签 java eclipse maven

我有一个 Maven java web 应用程序 (.WAR) 项目,其中包含多个库,包括 Wicket 库(但我不认为问题出在 wicket 本身,而是使用 maven)。

这就是问题所在:即使我只包含 Wicket 6.20.0,生成的 .WAR 包含 Wicket 库的两个副本:6.20.06.18.0,如您在此屏幕截图中所见:

enter image description here

考虑到一些相互冲突的导入,我使用以下方法打印了依赖关系树:

mvn dependency:tree

commnad...但是在依赖关系树中没有提到 Wicket 6.18.0!我还使用 Eclipse 的“依赖关系层次结构” View 进行了仔细检查,我可以确认没有任何导入痕迹。

我什至使用 Eclipse 在整个工作区中搜索字符串“6.18.0”,但无处可寻!

我如何找出导致包含该库的重复版本的原因?

最佳答案

Maven 不以这种方式工作。
多个具有相同 artifactId 和 groupId 但具有不同版本的依赖项的解析将导致单个依赖项(使用的版本是不确定的)。

在 WAR 的同一个 lib 文件夹中存在两个具有相同 artifactId 和 groupId 但具有两个不同版本的 Artifact 可能与以下之一有关:

  • 您不执行mvn clean package,而只执行mvn package

  • 您使用的是有漏洞的 Maven war 插件版本。尝试更新它以检查。

  • 您有一个 Maven 插件,它在构建组件期间将 Wicket jars 6.18.0 复制到目标文件夹的 WEB-INF/lib 文件夹中。

    <
  • 您正在构建的 Maven WAR 项目具有 WAR 类型的 Artifact 作为依赖项。在这种情况下,WAR 依赖项的依赖项是这样的 overlaid在您正在构建的 WAR 项目中。


一个有趣的 Maven 问题,关于由于 WAR 依赖性而导致的重复 JAR:

JARs with different versions can be in WEB-INF/lib with war as dependencies


Your answer和你的 comment表示实际上您的构建中有 WAR 依赖项。
不幸的是,并没有真正好的和长期有效的解决方案来绕过这个限制。

正如我在评论中所说,使用 Maven war 插件的 packagingExcludes 属性是解决实际问题的有效解决方法:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.4</version>
    <configuration>
        <!-- ... -->
        <packagingExcludes>WEB-INF/lib/wicket-*-6.18.0.jar</packagingExcludes>
    </configuration>
</plugin>

但请注意,随着时间的推移,使用它会使您的构建变得不那么健壮。 当您更新 WAR 依赖项的版本及其新版本时,它会再次拉出不同版本的 wicket,您仍然有可能在构建的 WAR 中拥有具有两个不同版本的重复 jar。

使用 the overlay通过指定 maven-war-pluginoverlay 元素的功能通常更好,因为它专注于应用于 war 依赖项的覆盖。它及早解决了问题。 因此,您可以定义从 WAR 依赖项中排除任何 wicket JAR:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <version>2.4</version>
    <artifactId>maven-war-plugin</artifactId>
    <configuration>     
        <overlays>
            <overlay>
                <groupId>com.whatever.youlike</groupId> 
                <artifactId>myArtifact</artifactId>
                <excludes>
                    <exclude>WEB-INF/lib/wicket-*.jar</exclude>                 
                </excludes>
            </overlay>
        </overlays>
    </configuration>
</plugin>

这种方式更好,但这仍然是一种解决方法。
更新依赖项 WAR 并提取在您的实际构建中声明但具有不同版本的新依赖项(Wicket 除外)的那一天,您可能会遇到相同类型的问题。

我认为只有在我们别无选择时才应该声明对 WAR Artifact 的依赖。
由于 poms 和项目重构是可能的,因此引入两个 WAR 所依赖的公共(public) JAR 依赖项并且仅包含两个 WAR 的公共(public)源和资源使事情变得更简单。

关于java - 为什么 Maven 包含相同依赖项的多个版本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44631683/

相关文章:

java - 没有这样的元素异常(exception)

java - Dijkstra 算法模拟

java - 作为 Maven 项目运行和调试 Eclipse RCP

java - "Unresolved requirement: Import-Package: javax.ws.rs"在 Tomcat 上为 Liferay 部署 OSGi 模块时

java - 错误 :java: invalid source release: 8 in Intellij. 是什么意思?

java - 如何编译这个项目

java - 泛型和 Class.asSubclass

java - 如何向安卓键盘添加一些东西?

spring - 我怎么知道应该将哪个 maven 依赖添加到 pom.xml

maven - 在maven项目中查找依赖(反向依赖)