Gradle:Springboot 覆盖依赖项(球衣和 apache httpclient)
Posted
技术标签:
【中文标题】Gradle:Springboot 覆盖依赖项(球衣和 apache httpclient)【英文标题】:Gradle: Springboot overriding dependencies (jersey and apache httpclient) 【发布时间】:2020-03-15 04:56:02 【问题描述】:我有一个非常简单的 springboot 应用程序用于测试目的。
这是我的 build.gradle:
plugins
id 'org.springframework.boot' version '2.1.0.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id 'java'
sourceCompatibility = '1.8'
repositories
mavenCentral()
dependencies
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.mandas:docker-client:2.0.2'
org.mandas:docker-client:2.0.2
对org.glassfish.jersey.core:jersey-client:2.28
具有传递依赖。然而 gradle 然后拉版本 2.27
而不是 2.28
。
如果我运行./gradlew dependencyInsight --dependency org.glassfish.jersey.core:jersey-client
,我会得到以下输出:
org.glassfish.jersey.core:jersey-client:2.27 (selected by rule)
...
org.glassfish.jersey.core:jersey-client:2.27
\--- org.glassfish.jersey.connectors:jersey-apache-connector:2.27
\--- org.mandas:docker-client:2.0.2 (requested org.glassfish.jersey.connectors:jersey-apache-connector:2.28)
\--- compileClasspath
org.glassfish.jersey.core:jersey-client:2.28 -> 2.27
\--- org.mandas:docker-client:2.0.2
\--- compileClasspath
似乎spring-boot-starter-web
在某种程度上依赖于org.glassfish.jersey.core:jersey-client:2.27
。但是,如果我使用 ./gradlew dependencies
打印所有依赖项,我看不到来自 spring-boot-starter-web
的对 org.glassfish.jersey.core:jersey-client:2.27
的依赖项。
然而,在网上搜索了一下,我发现了另一种追踪依赖项的方法:
grep -r "2.27" ~/.gradle/caches/modules-2/files-2.1/*
像这样,我能够追踪到 2.27 版的引入位置。它似乎在以下 poms 中声明:
spring-boot-dependencies-2.1.0.RELEASE.pom spring-boot-autoconfigure-2.1.0.RELEASE.pom我现在的问题是多方面的:
首先,为什么spring-boot-starter-web
依赖jersey
?我一直认为,如果我们想明确地使用 jersey
而不是 spring
实现,我们将包括 spring-boot-starter-jersey
。
为什么我在运行./gradlew dependencies
时看不到spring-boot-starter-web
依赖于org.glassfish.jersey.core:jersey-client:2.27
。显然,它在降级版本时必须在某处依赖它。
为什么 2.28 版本降级到 2.27 版本?我如何知道 Spring Boot 应用了哪个策略以便为特定版本做出选择。
应用程序运行良好,但现在我遇到了版本冲突,我应该如何最好地处理这个问题?仅使用 v2.28 而不是 v2.27 是否可行。我想这也指的是我第一个回答为什么 spring-boot 实际上使用jersey
。
我知道这是多个问题,但我认为最好在一个问题中提出这些问题,而不是将它们分散到多个问题上,因为它们都与相同的上下文相关。
顺便说一句:这不仅发生在org.glassfish.jersey.core:jersey-client
上。同样的事情也适用于org.apache.httpcomponents:httpclient
。
感谢您的帮助!
【问题讨论】:
【参考方案1】:首先,
spring-boot-starter-web
为什么要依赖球衣?我一直认为,如果我们想明确地使用jersey
而不是spring
实现,我们将包括spring-boot-starter-jersey
。
它没有。相反,它依赖于 Tomcat。你是正确的,你需要球衣启动器来自动配置它。
为什么我在运行
./gradlew dependencies
时看不到spring-boot-starter-web
依赖于org.glassfish.jersey.core:jersey-client:2.27
。显然,它在降级版本时必须在某处依赖它。
因为它没有。更多内容如下。
为什么 2.28 版本降级到 2.27 版本?我如何知道 Spring Boot 应用了哪个策略以便为特定版本做出选择。
这是根本问题。我会在下面解释。
应用程序运行得很好,但是现在我遇到了版本冲突,我应该如何最好地处理这个问题?仅使用 v2.28 而不是 v2.27 是否可行。我认为这也指的是我对为什么 spring-boot 实际上使用
jersey
的第一个答案。
这取决于。根据我的经验,你的依赖关系可能会通过升级和降级传递依赖关系来破坏,与它们已经构建和测试过的依赖关系相比,即使它只是一个小版本(我在看着你,SnakeYAML!)所以你真的只有试一试。通常升级比降级更安全,但有时还是会出问题。
这是球衣降级的交易。
Spring 依赖管理插件用于控制依赖的版本,包括直接的和传递的。
当您同时应用依赖管理插件和 Spring Boot 插件时,后者将应用其默认版本,该版本来自 Spring Boot BOM。您可以通过运行gradle dependencyManagement
来检查管理哪些依赖项以及在哪些版本中。
所有这一切的想法是,您可以获得一组已知可以很好地相互配合的依赖项。如果您喜欢其中一个托管依赖项的不同版本,则必须使用 dependencyManagement
扩展名对其进行配置(如文档中的 here 所述)。
这就是您的 Jersey 依赖项被降级的原因。
我个人不使用 Spring 依赖项管理插件,因为我喜欢在普通 Gradle 中处理依赖项的方式。所以我通常只是做这样的事情:
plugins
id 'org.springframework.boot' version '2.1.0.RELEASE'
id 'java'
dependencies
implementation platform("org.springframework.boot:spring-boot-dependencies:2.1.0.RELEASE")
在这种情况下,它将默认使用 Spring Boot BOM 中的依赖项,但如果有人需要更新版本,则不会降级它们。但如果需要,它会升级它们,如果你不想,也不必自己指定版本,在这种情况下,它将使用 BOM 中的版本。
【讨论】:
非常感谢。非常详细的信息。我想我现在明白了。只有一件事:我是否正确理解 spring 启动插件(与 spring-dependency-management 插件一起)保留了一个列表(bom),其中包含 Spring Boot(特定版本)可能具有的所有可能依赖项?他们如何选择在 bom 中包含哪些模块(不是版本)? 是的,您可以看到 BOM here,但我不知道他们使用什么标准来选择模块。他们只是说Each release of Spring Boot provides a curated list of dependencies that it supports
和The curated list contains all the spring modules that you can use with Spring Boot as well as a refined list of third party libraries
。
谢谢。我终于做了,似乎正在工作的是将它添加到我的 build.gradle:ext['jersey.version'] = '2.28'
和 ext['httpclient.version'] = '4.5.4'
。我目前仍在使用 Spring 依赖管理插件。以上是关于Gradle:Springboot 覆盖依赖项(球衣和 apache httpclient)的主要内容,如果未能解决你的问题,请参考以下文章
从 Gradle 中的 Spring Boot 中排除 Tomcat 依赖项
Spring boot 和 Gradle 多模块项目,无法正确加载依赖项