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


220

在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。在这种情况下,需要排除或覆盖版本。
Vinod Singh,2009年

1
使用常春藤。开玩笑。
杰克·多伦多

Answers:


54

对于maven2,没有一种方法可以做您描述的事情。对于Maven 3,有。如果您使用的是Maven 3,请查看此问题的其他答案

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


12
我建议不要制作自己的pom来解决排除问题。这使您的构建的可移植性大大降低,并降低了理解力。
布赖恩·福克斯

1
如果您不看过去的认可答案,请访问:jira.codehaus.org/browse/MNG-3832
Jakub Bochenski 2015年

@JakubBochenski我给出的答案是特定于maven 2的,这是该问题的标签(在我撰写此评论时)。您的链接仅与maven 3相关。无论如何,我已经编辑了答案链接以链接到更高评价的答案。
whaley 2015年

305

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

我有一个多模块项目,其中包含在两个WAR打包模块中引用的“ app”模块。这些WAR打包的模块之一实际上只需要域类(并且我还没有将它们与app模块分离)。我发现这可行:

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

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


9
*组和artifact的通配符似乎在maven 3中
起作用

22
我不知道您如何找到它,因为Maven 3明确警告有关星号的使用:[警告] <artifcat_id>的'dependencies.dependency.exclusions.exclusion.groupId'值为“ *”不会匹配有效的ID模式。[警告]强烈建议修复这些问题,因为它们会威胁到您的构建的稳定性。[警告]出于这个原因,将来的Maven版本可能不再支持构建此类格式错误的项目。您介意提供一些证据来证明它受支持并可以使用吗?否则,我认为您的评论极具误导性。

7
与Maven 3.0.4完美兼容。感谢了很多
Evgeny Goldin

1
Maven 3.0.4->它对我来说效果不佳。当我使用asterix或明确排除所有直接依赖项时,生成的jar会有很大不同。这可能与我使用maven-assembly-plugin创建胖子的事实有关。在这种情况下,建议的后推功能不起作用!
吉拉德·霍奇2013年

31
此方法有效。他们修复了其他人正在maven 3.2.1中进行报告的警告:issue.apache.org/jira/browse/MNG-3832
Ryan

32

我发现有用的一件事:

如果将带有排除项的依赖项放在项目的父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中的会同时指定版本和排除项。我在几乎所有项目中都使用了这种技术,并且消除了很多重复。


23

三年前,我建议使用“不存在版本99”,但现在我想出了一种更好的方法,尤其是因为版本99处于脱机状态:

在项目的父POM中,如果不需要的依赖性蔓延到构建中,请使用maven-enforcer-plugin使构建失败。可以使用插件的禁止依赖关系规则来完成此操作:

<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的<dependencyManagement>部分中:

<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>

这样,不需要的依赖项就不会意外出现(不同于只是一个<exclusion>容易忘记的provided依赖项),即使在编译期间它也不可用(与作用域不同),没有伪造的依赖项(与99版不同),并且它无需自定义存储库即可工作(与99版不同)。该方法甚至可以根据工件的版本,分类器,范围或整个groupId起作用- 有关详细信息,请参见文档


请注意,至少在Maven 3.1下,<configuration>从命令行执行目标时会忽略,并且必须直接在上移<plugin>
David Harkness 2014年

我刚刚发现了看起来像一个讨厌的Maven错误-版本3.5.2。我有一个带有子模块的项目,在父项目中确实排除了依赖项<dependencyManagement>mvn dependency:tree在该特定项目中运行,将完全没有排除的依赖性。但是所有导入该依赖项的项目都不会兑现<exclusions>另一个项目父项pom中的项目-被排除的项目会悄悄进入!!!我不得不直接移到<exclusions>每个模块pom。
cbaldan

11

我使用以下变通方法:不是在所有适当的依赖项中尝试排除工件,而是在顶层将依赖项绘制为“提供”。例如,为避免运送xml-apis“任何版本”:

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


6

有一个解决方法,如果将依赖项的范围设置为runtime,则将排除传递性依赖项。尽管请注意,这意味着如果要打包运行时依赖项,则需要添加其他处理。

要将运行时依赖项包含在任何包装中,可以将maven-dependency-plugin的复制目标用于特定工件


1
这帮助我解决了Android Dalvik编译器无法解决某些两级可及包含问题的问题-但我不得不使用<scope>provided</scope>而不是<scope>runtime</scope>
Garret Wilson,

6

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

<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>

3

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

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


请注意,如果您使用的是m2eclipse插件这只能
萨科酒店距离Mommaerts

2

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

如果存在需要从每个依赖项中排除的特定工件(例如commons-logging),则“不存在版本99”方法可能会有所帮助。


2012年更新:请勿使用此方法。使用maven-enforcer-plugin和exclusions。99版产生虚假的依赖关系,而99版存储库处于脱机状态(有类似的镜像,但您也不能永远依赖它们;最好只使用Maven Central)。


1

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


-2

在类路径中使用最新的Maven。它将删除重复的工件,并保留最新的Maven工件。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.