排除单个依赖项的所有传递依赖项

Posted

技术标签:

【中文标题】排除单个依赖项的所有传递依赖项【英文标题】:Exclude all transitive dependencies of a single dependency 【发布时间】:2010-10-07 13:30:13 【问题描述】:

在 Maven2 中,要排除单个传递依赖,我必须这样做:

<dependency>
  <groupId>sample.group</groupId>
  <artifactId>sample-artifactB</artifactId>
  <version>1</version>
   <exclusions>
     <exclusion>
       <groupId>sample.group</groupId>
       <artifactId>sample-artifactAB</artifactId>
     </exclusion>
   </exclusions>
</dependency>

这种方法的问题在于,我必须为sample-artifactB 贡献的每个传递依赖项执行此操作。

有没有办法使用某种通配符来一次排除所有传递依赖项而不是一个接一个?

【问题讨论】:

有时需要使用最新版本的库,比如 Spring 2.5.6,但其他一些依赖项包括旧版本,例如struts2-spring-plugin (2.1.6) 包括 Spring 2.5.3。在这种情况下,需要排除或覆盖版本。 使用常春藤。开个玩笑。 【参考方案1】:

对我有用的东西(可能是 Maven 的新功能)只是在排除元素中使用通配符。

我有一个多模块项目,其中包含在两个 WAR 打包模块中引用的“应用”模块。其中一个 WAR 打包的模块实际上只需要域类(我还没有将它们从应用程序模块中分离出来)。我发现这行得通:

<dependency>
    <groupId>$project.groupId</groupId>
    <artifactId>app</artifactId>
    <version>$project.version</version>
    <exclusions>
        <exclusion>
            <groupId>*</groupId>
            <artifactId>*</artifactId>
        </exclusion>
    </exclusions>
</dependency>

groupId 和 artifactId 上的通配符排除了所有通常会传播到使用此依赖项的模块的依赖项。

【讨论】:

组和工件的 * 通配符似乎在 maven 3 中工作 我不知道你是如何找到这个工作的,因为 Maven 3 明确警告使用星号:[WARNING] 'dependencies.dependency.exclusions.exclusion.groupId' for 值“*”与有效的 id 模式不匹配。 [警告] 强烈建议修复这些问题,因为它们会威胁您构建的稳定性。 [警告] 出于这个原因,未来的 Maven 版本可能不再支持构建此类格式错误的项目您介意提供一些证据证明它受支持并且可以使用吗?否则我会认为您的评论极具误导性。 与 Maven 3.0.4 完美配合。 非常感谢 maven 3.0.4 -> 它对我来说效果不佳。当我使用 asterix 或当我明确排除所有直接依赖项时,产生的 jar 非常不同。这可能与我使用 maven-assembly-plugin 创建一个胖 jar 的事实有关。在这种情况下,建议的 sulotion 不起作用! 此方法有效。他们修复了其他人在 maven 3.2.1 中报告的警告:issues.apache.org/jira/browse/MNG-3832【参考方案2】:

对于 maven2,没有办法按照您的描述进行操作。对于 Maven 3,有。如果您使用的是 maven 3,请参阅another answer for this question

对于 maven 2,我建议为具有 的依赖项创建自己的自定义 pom。对于需要使用该依赖项的项目,请将依赖项设置为您的自定义 pom 而不是典型的工件。虽然这不一定允许您使用单个 排除所有传递依赖项,但它确实允许您只需要编写一次依赖项,并且您的所有项目都不需要维护不必要的长排除列表。

【讨论】:

我建议不要制作自己的 pom 来解决排除问题。这会使您的构建变得不那么可移植,并降低了理解力。 如果你没有看过去接受的anwser:jira.codehaus.org/browse/MNG-3832 @JakubBochenski 我给出的答案是针对 maven 2 的,这就是这个问题的标签(在我写这篇评论的时候)。您的链接仅与 maven 3 相关。无论如何,我已经编辑了我的答案以链接到更受好评的答案。【参考方案3】:

我发现有用的一件事:

如果您将带有排除项的依赖项放在项目的父 POM 的 dependencyManagement 部分中,或者放在可导入的依赖项管理 POM 中,则无需重复排除项(或版本)。

例如,如果您的父 POM 有:

<dependencyManagement>
    <dependencies>
    ...         
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.2.1</version>
            <exclusions>
                <exclusion>
                    <groupId>junit</groupId>
                    <artifactId>junit</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
     ....
  </dependencies>
</dependencyManagement>

那么你项目中的模块可以简单的声明依赖为:

        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
        </dependency>

父 POM 中的 将指定版本和排除项。我几乎在我们所有的项目中都使用了这种技术,它消除了很多重复。

【讨论】:

【参考方案4】:

Three years ago我建议使用版本 99 不存在,但现在我想出了更好的方法,尤其是因为版本 99 已离线:

在项目的父 POM 中,如果不需要的依赖项蔓延到构建中,请使用 maven-enforcer-plugin 使构建失败。这可以使用插件的banned dependencies 规则来完成:

<plugin>
    <artifactId>maven-enforcer-plugin</artifactId>
    <version>1.0.1</version>
    <executions>
        <execution>
            <id>only-junit-dep-is-used</id>
            <goals>
                <goal>enforce</goal>
            </goals>
            <configuration>
                <rules>
                    <bannedDependencies>
                        <excludes>
                            <exclude>junit:junit</exclude>
                        </excludes>
                    </bannedDependencies>
                </rules>
            </configuration>
        </execution>
    </executions>
</plugin>

然后,当它提醒您有关不需要的依赖项时,将其排除在父 POM 的 &lt;dependencyManagement&gt; 部分中:

<dependency>
    <groupId>org.springframework.batch</groupId>
    <artifactId>spring-batch-test</artifactId>
    <version>2.1.8.RELEASE</version>
    <exclusions>
        <exclusion>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
        </exclusion>
    </exclusions>
</dependency>

这样不需要的依赖就不会意外出现(不像&lt;exclusion&gt; 那样容易忘记),即使在编译期间也不可用(不像provided 范围),没有虚假依赖项(与版本 99 不同),它可以在没有自定义存储库的情况下工作(与版本 99 不同)。这种方法甚至可以基于工件的版本、分类器、范围或整个 groupId - see the documentation 了解详细信息。

【讨论】:

请注意,至少在 Maven 3.1 下,&lt;configuration&gt; 在从命令行执行目标时会被忽略,必须直接向上移动到 &lt;plugin&gt; 下。 我刚刚发现了一个看起来很讨厌的 Maven 错误 - 版本 3.5.2。我有一个带有子模块的项目,我确实在父级的&lt;dependencyManagement&gt; 部分排除了依赖项。在该特定项目中运行 mvn dependency:tree 将完全没有排除的依赖项。但是所有导入该依赖项的项目都不会遵守来自另一个项目父 pom 的&lt;exclusions&gt; - 被排除的项目将潜入!!!我不得不将&lt;exclusions&gt; 直接移动到每个模块 pom。【参考方案5】:

我使用以下解决方法:我没有尝试在所有适当的依赖项中排除工件,而是在顶层将依赖项绘制为“已提供”。 例如,为了避免发送 xml-apis “whatever version”:

    <dependency>
        <groupId>xml-apis</groupId>
        <artifactId>xml-apis</artifactId>
        <version>[1.0,]</version>
        <scope>provided</scope>
    </dependency>

【讨论】:

【参考方案6】:

目前,无法一次排除多个传递依赖项,但在 Maven JIRA 网站上有一个功能请求:

https://issues.apache.org/jira/browse/MNG-2315

【讨论】:

【参考方案7】:

有一个解决方法,如果你将依赖的范围设置为 runtime,传递依赖将被排除。但请注意,这意味着如果您想打包运行时依赖项,则需要添加额外的处理。

要在任何打包中包含运行时依赖项,您可以使用 maven-dependency-plugin 的copy goal for a specific artifact。

【讨论】:

这帮助我解决了 android Dalvik 编译器无法处理一些两级传递包含的问题 --- 但我不得不使用 &lt;scope&gt;provided&lt;/scope&gt; 而不是 &lt;scope&gt;runtime&lt;/scope&gt;【参考方案8】:

如果您需要从要包含在程序集中的依赖项工件中排除所有传递依赖项,您可以在程序集插件的描述符中指定:

<assembly>
    <id>myApp</id>
    <formats>
        <format>zip</format>
    </formats>
    <dependencySets>
        <dependencySet>
            <useTransitiveDependencies>false</useTransitiveDependencies>
            <includes><include>*:struts2-spring-plugin:jar:2.1.6</include></includes>
        </dependencySet>
    </dependencySets>
</assembly>

【讨论】:

【参考方案9】:

如果您在 Eclipse 下开发,您可以在 POM 编辑器(启用高级选项卡)依赖关系图中查找您要从项目中排除的依赖关系,然后:

右键单击它->“排除 Maven Artifact ...”,Eclipse 将为您进行排除,而无需找出 lib 链接的依赖项。

【讨论】:

请注意,这仅在您使用 m2eclipse 插件时才有效【参考方案10】:

您排除所有传递依赖的原因是什么?

如果您需要从每个依赖项中排除特定的工件(例如 commons-logging),Version 99 Does Not Exist 方法可能会有所帮助。


2012 年更新:不要使用这种方法。使用maven-enforcer-plugin and exclusions。版本 99 产生虚假的依赖关系,版本 99 存储库处于脱机状态(有 similar mirrors,但您也不能依赖它们永远在线;最好只使用 Maven Central)。

【讨论】:

【参考方案11】:

在一个类似的问题中,我使用提供的范围声明了所需的依赖项。 使用这种方法,可以获取传递依赖项,但不包含在包阶段,这是您想要的。 在维护方面我也喜欢这个解决方案,因为不需要维护 pom 或 whaley 解决方案中的自定义 pom;只需要在容器中提供具体的依赖即可完成

【讨论】:

【参考方案12】:

在你的类路径中使用最新的 maven.. 它将删除重复的工件并保留最新的 maven 工件..

【讨论】:

以上是关于排除单个依赖项的所有传递依赖项的主要内容,如果未能解决你的问题,请参考以下文章

为啥有排除 pom.xml / maven 中依赖项的依赖项的选项?

Apache Ivy 排除依赖项的标记

我是不是必须明确检查/履行(Java)项目的所有传递依赖项的许可证?

使用 pipenv 安装本地依赖项的依赖项

如何在不触及其他依赖项的情况下更新单个 pod

idea单元测试排除其它依赖项的影响的配置