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

Mas*_*r_T 5 java eclipse maven

我有一个Mavenjava Web应用程序(.WAR)项目,包括几个库,包括Wicket库(但我不认为问题是wicket本身,而是maven).

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

在此输入图像描述

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

mvn dependency:tree
Run Code Online (Sandbox Code Playgroud)

commnad ...但在依赖树中没有提到Wicket 6.18.0!我还使用Eclipse的"依赖层次结构"视图进行了双重检查,我可以确认没有导入的痕迹.

我甚至用Eclipse在整个工作区中搜索字符串"6.18.0",但它无处可寻!

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

dav*_*xxx 6

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

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

  • 你不是mvn clean package只执行而是执行mvn package.

  • 你使用Maven war插件的bugged版本.尝试更新它以检查.

  • 你有一个Maven插件,可以WEB-INF/lib在组件构建过程中将Wicket jar 6.18.0复制到目标文件夹的文件夹中.

  • 您正在构建的maven WAR项目具有WAR类型的工件作为依赖项.在这种情况下,WAR依赖关系的依赖关系会覆盖在您正在构建的WAR项目中.


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

具有不同版本的JAR可以在WEB-INF/lib中使用war作为依赖项


您的答案评论表明您的构建中实际上存在WAR依赖关系.
不幸的是,没有一个好的和长期有效的解决方案来绕过这个限制.

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

<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>
Run Code Online (Sandbox Code Playgroud)

但要注意,使用它会使你的构建在整个时间内不那么健壮.在您更新WAR依赖项版本的那一天,以及在新版本中,它再次提取不同版本的wicket,您仍然有可能在构建的WAR中具有两个不同版本的重复jar.

通过指定元素来使用叠加特征通常更好,因为它侧重于应用于战争依赖性的叠加.它很早就解决了这个问题.因此,您可以定义从WAR依赖项中排除任何wicket JAR:overlaymaven-war-plugin

<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>
Run Code Online (Sandbox Code Playgroud)

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

我认为只应该在我们没有选择的情况下声明对WAR工件的依赖.
由于poms和项目重构是可能的,因此引入两个WAR所依赖的公共JAR依赖关系并且仅包含两个WAR的公共源和资源使事情变得更简单.