有没有办法在全球范围内排除Maven依赖关系?


92

我试图找到一种“通用”的方法来从中排除传递依赖,而不必从依赖它的所有依赖中排除它。例如,如果要排除slf4j,请执行以下操作:

  <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-jmx</artifactId>
    <version>3.3.2.GA</version>
    <exclusions>
      <exclusion>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
      </exclusion>
    </exclusions>
  </dependency>
  <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>3.4.0.GA</version>
    <type>jar</type>
    <exclusions>
      <exclusion>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
      </exclusion>
    </exclusions>
  </dependency>

这部分是为了清理pom文件,部分是为了避免以后人们添加依赖于该被排除依赖项的依赖关系而忘记了排除它的问题。

有办法吗?


2
不能解决问题,但是maven-enforcer-plugin具有禁止的依赖项功能,如果不需要的依赖项潜入,构建将失败。您仍然必须手动排除它们,尽管:-/
dnault

此处提供了一个替代答案:stackoverflow.com/a/39979760/363573
Stephan

Answers:


69

这有帮助吗?http://jlorenzen.blogspot.com/2009/06/maven-global-excludes.html

“假设我想从我的WAR中排除avalon框架,我将在项目POM中添加以下内容,其范围为提供的范围。这适用于所有传递依赖项,并且您只需指定一次即可。

<dependencies>
  <dependency>
      <artifactId>avalon-framework</artifactId>
      <groupId>avalon-framework</groupId>
      <version>4.1.3</version>
      <scope>provided</scope>
  </dependency>
</dependencies>

在父POM中指定它时,这甚至可以工作,这将防止项目在所有子POM中都必须声明它。”


49
它仍然只是部分破解-依赖关系不会最终出现在构建工件中,但在测试期间仍然可用。
Tuukka Mustonen 2012年

@TuukkaMustonen那么runtime范围而不是provided范围呢?
斯蒂芬

如果项目的其他位置包含avalon-framework 4.1.3+,会发生什么情况?在此处查看回复:stackoverflow.com/a/39979760/363573
Stephan

我不再使用Maven了,所以我无法测试其他答案,但是我鼓励人们考虑一下它们,以防万一其中的内容不是部分破解,根据@TuukkaMustonen
Joffer

18

我创建了一个空的jar并创建了此依赖关系:

<dependency>
    <groupId>commons-logging</groupId>
    <artifactId>commons-logging</artifactId>
    <scope>system</scope>
    <systemPath>${basedir}/src/lib/empty.jar</systemPath>
    <version>0</version>
</dependency>

这并不完美,因为从现在开始,您的编译/测试路径中将有一个空jar。但这仅仅是装饰性的。


3
system范围现在已经过时:maven.apache.org/guides/introduction/...
杰森-杨

为避免使用system范围,请参见虚拟Maven存储库version99.grons.nl(警告:仅HTTP)或(仅对于commons-logging / log4j)请参见此处的“替代3)空工件”:slf4j.org/faq.html#exceptionJCL
seanf

16

扩展dnault的评论

可以使用Maven Enforcer插件的“禁止的依赖项”规则来确保排除依赖项。仍然必须手动排除它们,但是如果有人错误地将依赖关系添加到其他地方,则构建将失败。

<dependencies>
  <dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-jmx</artifactId>
    <version>3.3.2.GA</version>
    <exclusions>
      <exclusion>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
      </exclusion>
    </exclusions>
  </dependency>
</dependencies>

<plugins>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-enforcer-plugin</artifactId>
    <version>1.4.1</version>
    <executions>
      <execution>
        <goals>
          <goal>enforce</goal>
        </goals>
        <configuration>
          <rules>
            <bannedDependencies>
              <excludes>
                <exclude>org.slf4j:slf4j-api</exclude>
              </excludes>
            </bannedDependencies>
          </rules>
        </configuration>
      </execution>
    </executions>
  </plugin>
</plugins>

也有一个开放功能的要求:MNG-1977全局依赖项排除


2
在您回答并阅读了您提供的链接上的讨论之后,我意识到不想要的jar有时会变成胖jar,这仅仅是因为本地和服务器上使用的maven版本不同,所以如果不严格执行打包逻辑,它们可以添加完全不同的依赖版本。为了解决类似的问题,我在<goal> repackage </ goal>中使用了spring-boot-maven-plugin配置/ excludes / exclude。
aprodan

10

提醒一下,这是Maven官方文档的答案:

为什么在每个依赖项而不是在POM级别上进行排除

这样做主要是为了确保依赖关系图是可预测的,并防止继承效应排除不应排除的依赖关系。如果您采用了不得已的方法并且必须排除在外,则应该绝对确定哪个依赖项带来了该有害的传递性依赖项。

如果要使构建更可靠,可以使用版本范围。这将确保没有任何新版本的依赖项可以干扰项目。

<dependency>
   <groupId>org.slf4j</groupId>
   <artifactId>slf4j-api</artifactId>
   <version>[1.4.2,)</version>
   <scope>provided</scope>
</dependency>

任何大于等于1.4.2的slf4j-api版本都将在运行时(从配置的类路径或容器中)视为已提供(提供)。

参考文献

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.