Gradle: Springboot 重写依赖(jersey 和 apache httpclient)

Gradle: Springboot overriding dependencies (jersey and apache httpclient)

我有一个非常简单的spring引导应用程序用于测试目的。

这是我的 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.2org.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 中声明:

我现在的问题是多方面的

我知道这些是多个问题,但我认为最好在一个问题中提出,而不是分散在多个问题上,因为它们都与相同的上下文相关。

顺便说一句:这不仅发生在 org.glassfish.jersey.core:jersey-client 身上。完全相同的事情适用于 org.apache.httpcomponents:httpclient.

感谢您的帮助!

First of all, why does spring-boot-starter-web depend on jersey? I was always under the impression that if we want to explicitly use jersey over the spring implementation we would include spring-boot-starter-jersey.

没有。相反,它取决于 Tomcat。你是对的,你需要 jersey starter 来自动配置它。

Why can't I see that spring-boot-starter-web depends on org.glassfish.jersey.core:jersey-client:2.27 when running ./gradlew dependencies. Obviously there must be a dependeny on it somewhere as it downgrades the version.

因为没有。更多内容见下文。

Why is version 2.28 downgraded to version 2.27? How can I know which policy is applied by spring boot in order to make a choice for a specific version.

这是根本问题。我会在下面解释。

The application is running perfectly fine, but now as i got a version conflict, how should i best handle this? Is it a viable option to just use v2.28 instead of v2.27. I think this also refers to my first answer on why spring-boot is actually using jersey.

视情况而定。根据我的经验,与构建和测试的传递依赖相比,你的依赖可能会通过升级和降级传递依赖来破坏,即使它只是一个次要版本(我在看着你,SnakeYAML!)所以你真的只是有试一试。通常升级比降级更安全,但有时还是会出问题。


这是关于球衣降级的协议。

Spring 依赖管理插件用于控制依赖的版本,包括直接依赖和传递依赖。

当您同时应用依赖管理插件和 Spring 启动插件时,后者将应用其默认版本,该版本来自 Spring 启动 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 引导 BOM 中的依赖项,但如果有人需要更新版本,则不会降级它们。但它会在需要时升级它们,如果你不想,你也不必自己指定版本,在这种情况下,它会使用 BOM 中的版本。