使用Gradle构建带有Spring Boot依赖项的“fat jar”

12

我正在使用Gradle构建和打包一个非常简单的Spring Boot应用程序(99%静态内容),将其打包成带有嵌入式Tomcat的jar文件。

我尝试创建这个jar文件,开始结果是86k,并且无法启动,因为缺少一些Spring Boot类。 我得出结论,我制作的这个jar文件不包含应用程序的任何依赖项,并且由于我确实需要完全自包含的jar文件,所以我应该做更多的研究。

这就是当我发现了建议添加 from {configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } 部分到“jar”时,它会导致它拉取所有的依赖关系。(我希望如此)。我熟悉三元运算符的概念,并且我可以看到它在这里尝试做什么。

不幸的是,它仍然无法工作!这是我启动时收到的错误,并附上我的build.gradle。

我想要一个完全包含在jar中的嵌入式Tomcat Spring Boot应用程序。我做了一些高度不寻常的事情吗?
此时任何帮助都将不胜感激。

(About 80 lines of successful Spring Boot launch messages followed immediately by:
18:16:54.890 [main] WARN  o.s.b.c.e.AnnotationConfigEmbeddedWebApplicationContext - Exception encountered during context initialization - cancelling refresh attempt
org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:132) [SpringWsTest1.jar:na]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:474) ~[SpringWsTest1.jar:na]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:117) [SpringWsTest1.jar:na]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:689) [SpringWsTest1.jar:na]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:321) [SpringWsTest1.jar:na]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:969) [SpringWsTest1.jar:na]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:958) [SpringWsTest1.jar:na]
    at ws.Application.main(Application.java:11) [SpringWsTest1.jar:na]
Caused by: org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.getEmbeddedServletContainerFactory(EmbeddedWebApplicationContext.java:182) [SpringWsTest1.jar:na]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:155) [SpringWsTest1.jar:na]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:129) [SpringWsTest1.jar:na]
    ... 7 common frames omitted
18:16:54.891 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@3b084709: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,application,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor,org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor,demoController,greetingController,org.springframework.boot.autoconfigure.AutoConfigurationPackages]; root of factory hierarchy
18:16:54.891 [main] ERROR o.s.boot.SpringApplication - Application startup failed
org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:132) ~[SpringWsTest1.jar:na]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:474) ~[SpringWsTest1.jar:na]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:117) ~[SpringWsTest1.jar:na]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:689) [SpringWsTest1.jar:na]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:321) [SpringWsTest1.jar:na]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:969) [SpringWsTest1.jar:na]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:958) [SpringWsTest1.jar:na]
    at ws.Application.main(Application.java:11) [SpringWsTest1.jar:na]
Caused by: org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.getEmbeddedServletContainerFactory(EmbeddedWebApplicationContext.java:182) ~[SpringWsTest1.jar:na]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:155) ~[SpringWsTest1.jar:na]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:129) ~[SpringWsTest1.jar:na]
    ... 7 common frames omitted
Exception in thread "main" org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:132)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:474)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:117)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:689)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:321)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:969)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:958)
    at ws.Application.main(Application.java:11)
Caused by: org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.getEmbeddedServletContainerFactory(EmbeddedWebApplicationContext.java:182)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:155)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:129)
    ... 7 more

我使用的 build.gradle:

println System.getProperty("java.home")

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.7.RELEASE")
    }
}

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'


jar {
    manifest {
        attributes 'Main-Class': 'ws.Application'
    }

    from {
        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
    }
}


repositories {
    mavenCentral()
}


dependencies {
    compile("org.springframework.boot:spring-boot-starter-web")
    testCompile("junit:junit")
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.3'
}

sourceCompatibility = 1.8
targetCompatibility = 1.8
3个回答

25

如果你使用gradle spring boot插件,则不需要为构建spring-boot应用程序的fat-jar工件创建额外的gradle配置,因为它已经有一个任务bootRepackage可以为你完成这项工作。你可以在这里这里的官方用户指南中了解更多信息。

只需删除你所做的所有解压依赖内容的操作,并使用该任务来获取包含应用程序的单个jar文件。

顺便说一句,你可能会对查看其他解决方案感兴趣,这些解决方案可能提供更好的存档大小,你可以在这篇文章中了解其中之一,称为Capsule。


我在文档中找到了bootRepackage任务,但由于我觉得文档没有完全解释清楚如何使用它,所以我还没有尝试使用它。但是,我错了,因为它就像文档中展示的那样简单,并且效果也非常好。感谢您提供Capsule的线索,我会尝试一下的。 - user1445967
2
@Stanislav 只是提醒一下,后面的链接已经不存在了。 - Christopher Will
5
自 Spring Boot 2.0 开始,Gradle 任务被称为 bootjar(相应地 bootwar),请参见 https://spring.io/blog/2017/04/05/spring-boot-s-new-gradle-plugin。 - Christopher Will

5

使用当前版本的Gradle,在你的build.gradle文件的顶部添加以下内容:

plugins {
    id "org.springframework.boot" version "2.0.0.RELEASE"
}

然后只需要运行gradle build命令,无需进行其他操作。

请访问此插件主页以查找最新版本。


1

我从@Stanislav的回答中找到了这个链接: https://docs.spring.io/spring-boot/docs/2.2.6.RELEASE/gradle-plugin/reference/html/#packaging-executable-wars-deployable,对我很有帮助。

为了构建jar,我使用了bootJar任务来编译jar。(./gradlew bootJar)。我的项目没有bootRepackage任务,使用./gradlew build没有生成包含所有所需依赖项的jar。也许我应该尝试使用像dependsOn这样的东西进行配置,但现在这对我来说已经足够了。

我有一个多模块项目,所以单模块项目的配置可能不同。我还在我的依赖项中使用了com.graphql-java:graphql-java-spring-boot-starter-webmvc:1.0,以及一些常规的spring boot依赖项,因此我的设置并非完全基本。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接