从 Gradle 中的 Spring Boot 中排除 Tomcat 依赖项

Posted

技术标签:

【中文标题】从 Gradle 中的 Spring Boot 中排除 Tomcat 依赖项【英文标题】:Excluding Tomcat dependencies from Spring Boot in Gradle 【发布时间】:2017-07-05 15:45:39 【问题描述】:

我正在使用带有 Jetty 的 Spring Boot,似乎我无法在我的 Gradle 构建文件中排除所有 Tomcat 依赖项。

build.gradle 的相关部分:

compile("org.springframework.boot:spring-boot-starter") 
    exclude module: "tomcat-embed-el"

compile("org.springframework.boot:spring-boot-starter-jetty")

compile("org.springframework.boot:spring-boot-starter-web") 
    exclude module: "spring-boot-starter-tomcat"

然而,当我运行gradle dependencies 时,部分tomcat 仍然存在,并导致WebSockets 出现问题:

...
|    
+--- org.springframework.boot:spring-boot-starter-web: -> 1.4.1.RELEASE
|    +--- org.springframework.boot:spring-boot-starter:1.4.1.RELEASE (*)
|    +--- org.hibernate:hibernate-validator:5.2.4.Final
|    |    +--- javax.validation:validation-api:1.1.0.Final
|    |    +--- org.jboss.logging:jboss-logging:3.2.1.Final -> 3.3.0.Final
|    |    \--- com.fasterxml:classmate:1.1.0 -> 1.3.1
|    +--- com.fasterxml.jackson.core:jackson-databind:2.8.3
|    |    +--- com.fasterxml.jackson.core:jackson-annotations:2.8.0 -> 2.8.3
|    |    \--- com.fasterxml.jackson.core:jackson-core:2.8.3
|    +--- org.springframework:spring-web:4.3.3.RELEASE
|    |    +--- org.springframework:spring-aop:4.3.3.RELEASE (*)
|    |    +--- org.springframework:spring-beans:4.3.3.RELEASE (*)
|    |    +--- org.springframework:spring-context:4.3.3.RELEASE (*)
|    |    \--- org.springframework:spring-core:4.3.3.RELEASE
|    +--- org.springframework:spring-webmvc:4.3.3.RELEASE
|    |    +--- org.springframework:spring-aop:4.3.3.RELEASE (*)
|    |    +--- org.springframework:spring-beans:4.3.3.RELEASE (*)
|    |    +--- org.springframework:spring-context:4.3.3.RELEASE (*)
|    |    +--- org.springframework:spring-core:4.3.3.RELEASE
|    |    +--- org.springframework:spring-expression:4.3.3.RELEASE (*)
|    |    \--- org.springframework:spring-web:4.3.3.RELEASE (*)
|    \--- org.springframework.boot:spring-boot-starter-tomcat:1.4.1.RELEASE
|         +--- org.apache.tomcat.embed:tomcat-embed-core:8.5.5
|         +--- org.apache.tomcat.embed:tomcat-embed-el:8.5.5
|         \--- org.apache.tomcat.embed:tomcat-embed-websocket:8.5.5
|              \--- org.apache.tomcat.embed:tomcat-embed-core:8.5.5
...

为什么spring-boot-starter-tomcat 不从spring-boot-starter-web 中排除?

【问题讨论】:

【参考方案1】:

啊哈,找到原因了。

我也有 compile("org.springframework.boot:spring-boot-starter-websocket") 依赖,它也依赖于 spring-boot-starter-tomcat。 Gradle 依赖输出误导我认为 spring-boot-starter-web 是 Tomcat 仍然存在的原因。

我必须添加以下内容:

compile("org.springframework.boot:spring-boot-starter-websocket") 
    exclude module: "spring-boot-starter-tomcat"

经验教训是,当您要排除某些内容时,请仔细检查所有依赖项以确保将其排除在所有位置之外。并且可以改进 gradle 依赖项输出以减少误导...

【讨论】:

感谢分享@Kresimir Nesek,拯救了我的一天!【参考方案2】:

我遇到了同样的问题,所以除了排除 spring-boot-starter-tomcat 我还必须排除 tomcat-embed-* jar,我这样做了通过 gradle 配置

configurations 
  compile.exclude module: 'spring-boot-starter-tomcat'
  compile.exclude group: 'org.apache.tomcat'

【讨论】:

谢谢老兄! Undertow 在 Eclipse 中工作,但不在 jar 中,添加它,使其工作。对于那些使用更新的 gradle 版本的人,不要将编译更改为实现。完全按照这里写的方式使用。【参考方案3】:

gradle 破解

在没有上述模块排除的情况下,使用 Gradle 6 这对我有用:

configurations 
    compile.exclude module: 'spring-boot-starter-tomcat'

插件配置

spring boot gradle plugin documentation 4.2.1 建议像这样声明提供的依赖项(假设你建立了一个战争):

providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'

依赖关系不会从战争中移除,而是移动到它们通常不会造成伤害的位置。

WEB-INF/lib-provided/spring-boot-starter-tomcat-2.2.4.RELEASE.jar
WEB-INF/lib-provided/tomcat-embed-websocket-9.0.30.jar
WEB-INF/lib-provided/tomcat-embed-core-9.0.30.jar
WEB-INF/lib-provided/tomcat-embed-el-9.0.30.jar

【讨论】:

这只是一个简单且非常优雅的解决方案。所有与 tomcat 相关的库都移动到 WEB-INF 内的 lib-provided 文件夹中,其余库保留在 WEB-INF/lib 文件夹中。 此解决方案的好处是您仍然拥有所有部署选项。战争文件可以安装在码头,你仍然可以在独立模式下运行战争执行 java -jar myapp.war【参考方案4】:

使用 kotlin gradle dsl:

configurations 
    implementation.configure 
       exclude(module = "spring-boot-starter-tomcat")
       exclude("org.apache.tomcat")
    


【讨论】:

【参考方案5】:

Krešimir Nesek 的回答启发了我解决我的错误。但我用一点不同的方式解决它。

我的问题是通过在 Kotlin 中基于 WebFlux 和 springCoroutines 构建的模块中包含带有 Spring-Boot 的其他模块来调用的。

我在 Kotlin 中的方式是:

 exclude("org.springframework.boot", "spring-boot-starter-tomcat")

第一个参数"org.springframework.boot" 用于组,第二个参数用于特定模块。

【讨论】:

以上是关于从 Gradle 中的 Spring Boot 中排除 Tomcat 依赖项的主要内容,如果未能解决你的问题,请参考以下文章

Gradle 学习总结—— 如何将 Spring Boot 构建工具从 Maven 迁移到 Gradle

多模块 Spring Boot 项目中的 Gradle 依赖插件

Gradle 无法同步 Spring Boot 项目

从 Gradle 将系统属性传递到 Spring Boot

Spring Boot 项目中的 Gradle 无法识别路径中的 Java jdk

在 Spring Boot 中使用 Gradle 从 Swagger OpenAPI 生成 RestClient 存根