有没有办法全局排除 Maven 依赖项?
Posted
技术标签:
【中文标题】有没有办法全局排除 Maven 依赖项?【英文标题】:Is there a way to exclude a Maven dependency globally? 【发布时间】:2011-06-10 14:53:09 【问题描述】:我正在尝试找到一种“通用”方式来排除传递依赖项,而不必将其从依赖它的所有依赖项中排除。例如,如果我想排除 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 文件,部分是为了避免将来人们添加依赖于排除的依赖项的依赖项而忘记排除它的问题。
有办法吗?
【问题讨论】:
不能解决问题,但是 maven-enforcer-plugin 有一个 banned dependencies feature,如果不需要的依赖项潜入,它将导致构建失败。但您仍然必须手动排除它们:-/ 此处提供了替代答案:***.com/a/39979760/363573 【参考方案1】:这有帮助吗? http://jlorenzen.blogspot.com/2009/06/maven-global-excludes.html
“假设我想从我的 WAR 中排除 avalon-framework,我会将以下内容添加到我的项目 POM 中,范围为提供。这适用于所有传递依赖项,并允许您指定一次。
<dependencies>
<dependency>
<artifactId>avalon-framework</artifactId>
<groupId>avalon-framework</groupId>
<version>4.1.3</version>
<scope>provided</scope>
</dependency>
</dependencies>
这甚至在父 POM 中指定它时也有效,这将阻止项目必须在所有子 POM 中声明它。"
【讨论】:
它仍然只是部分破解 - 依赖项不会最终出现在构建工件中,但它在测试期间仍然可用。 @TuukkaMustonenruntime
范围而不是 provided
范围呢?
如果 avalon-framework 4.1.3+ 包含在项目的其他地方会怎样?在此处查看回复:***.com/a/39979760/363573
我不再使用 Maven,所以我无法测试其他答案,但我鼓励人们考虑它们,以防万一不是部分破解,根据@TuukkaMustonen【参考方案2】:
我创建了一个空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。但这只是装饰性的。
【讨论】:
system
范围现已弃用:maven.apache.org/guides/introduction/…
为了避免使用 system
范围,请参阅虚拟 Maven 存储库 version99.grons.nl(警告:仅限 HTTP)或(仅适用于 commons-logging/log4j)请参阅此处的“替代 3)空工件”: slf4j.org/faq.html#excludingJCL【参考方案3】:
提醒一下,这里是来自 Maven 官方文档的答案:
为什么要根据每个依赖项而不是在 POM 级别进行排除
这主要是为了确保依赖关系图是可预测的,并防止继承效应排除不应该排除的依赖关系。如果您使用最后的方法并且必须排除,您应该绝对确定您的哪些依赖项带来了不需要的传递依赖项。
如果想要使构建更加健壮,可以使用版本范围。这将确保没有新版本的依赖项可以干扰项目。
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>[1.4.2,)</version>
<scope>provided</scope>
</dependency>
任何 slf4j-api 版本 >= 1.4.2 都将被视为在运行时提供(提供),无论是来自配置的类路径还是容器。
参考文献
Maven version range Optional Dependencies and Dependency Exclusions【讨论】:
【参考方案4】:扩展dnault's comment:
可以使用Maven Enforcer plugin's Banned Dependencies rule 来确保排除依赖项。仍然需要手动排除它们,但如果有人错误地将依赖项添加到其他地方,构建将失败。
<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 Global dependency exclusions
【讨论】:
根据您的回答并阅读您提供的链接中的讨论,我意识到有时不需要的 jar 会进入胖 jar,因为本地和服务器上使用的 maven 版本不同,因此打包逻辑可以添加完全不同的版本如果没有严格执行依赖项。为了解决我的类似问题,我使用 spring-boot-maven-plugin configuration/excludes/exclude for以上是关于有没有办法全局排除 Maven 依赖项?的主要内容,如果未能解决你的问题,请参考以下文章
为啥有排除 pom.xml / maven 中依赖项的依赖项的选项?
有没有办法在 maven 尝试解决它们之前安装 maven 依赖项?
不排除 Maven 瞬态依赖项(库/jar vaadin json)