java Gradle:使用 Spring Boot 依赖项构建“fat jar”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33578495/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 21:52:00  来源:igfitidea点击:

Gradle: Build 'fat jar' with Spring Boot Dependencies

javagradlejarspring-boot

提问by user1445967

I am using Gradle to build and package a very simple spring boot application (99% static content) into a jar with embedded tomcat.

我正在使用 Gradle 构建一个非常简单的 Spring Boot 应用程序(99% 静态内容)并将其打包到一个带有嵌入式 tomcat 的 jar 中。

I tried creating said jar, at first the result was 86k and did not launch, because it was missing some Spring boot classes. I concluded this jar I made contained none of the application's dependencies, and since I did want a completely self-contained jar, I should do more research.

我尝试创建所述 jar,起初结果是 86k 并且没有启动,因为它缺少一些 Spring 引导类。我得出结论,我制作的这个 jar 不包含任何应用程序的依赖项,而且由于我确实想要一个完全独立的 jar,我应该做更多的研究。

This is when I discovered the advice to add the from {configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }section to the 'jar' which causes it to pull in all of the dependencies. (I hope). I'm familiar with the idea of the ternary operator and I can see what it's trying to do here.

这是当我发现将from {configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }部分添加到“jar”的建议时,这会导致它引入所有依赖项。(我希望)。我熟悉三元运算符的想法,我可以在这里看到它试图做什么。

Unfortunately it is still not working! Here is the error I get on launch, and below is my build.gradle.

不幸的是它仍然无法正常工作!这是我在启动时遇到的错误,下面是我的 build.gradle。

I want a spring boot application with embedded tomcat fully contained in a jar. Am I doing something highly unconventional?
Any help at this point would be greatly appreciated.

我想要一个带有完全包含在 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 I am using:

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

回答by Stanislav

You don't need to make yourself additional gradle configurations for building a fat-jar artifact of spring-boot application, since you use a gradle spring boot plugin. It already has a task bootRepackageto do it for you. You can read about it in official user guide hereand here.

您无需为构建 spring-boot 应用程序的 fat-jar 工件而进行额外的 gradle 配置,因为您使用了 gradle spring boot 插件。它已经有一项任务bootRepackage要为您完成。您可以在此处此处的官方用户指南中阅读有关它的信息

Just delete all you've done to unzip dependencies content and use this task to get a single jar file with your application.

只需删除您为解压缩依赖项内容所做的所有工作,并使用此任务为您的应用程序获取单个 jar 文件。

By the way, you may be interested to look at some other solution, which possibly could provide a better archive sizes, you can read about one of them, called Capsule, in this article.

顺便说一句,您可能有兴趣查看一些其他解决方案,它可能会提供更好的存档大小,您可以在本文中阅读其中一个称为 Capsule 的内容

回答by Bohemian

With current versions of gradle, add this at the top of your build.gradlefile:

使用当前版本的 gradle,在build.gradle文件顶部添加:

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

then just gradle build- you don't need to do anything more.

那么就gradle build- 你不需要再做任何事情了。

See this plugin's homepageto find the latest version.

查看此插件的主页以查找最新版本。

回答by retodaredevil

I found this link from @Stanislav's answer: https://docs.spring.io/spring-boot/docs/2.2.6.RELEASE/gradle-plugin/reference/html/#packaging-executable-wars-deployableto be very helpful.

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

To to build the jar, I used the bootJartask to compile the jar. (./gradlew bootJar). My project doesn't have the bootRepackagetask and using a ./gradlew builddid not generate a jar with all the dependencies it needed. Maybe that's something I should try to configure using something like dependsOn, but for now this works for me.

为了构建 jar,我使用bootJar任务来编译 jar。( ./gradlew bootJar). 我的项目没有bootRepackage任务,并且使用 a./gradlew build没有生成包含它需要的所有依赖项的 jar。也许这是我应该尝试使用类似的东西来配置的东西dependsOn,但现在这对我有用。

I have a multimodule project, so maybe configuration is different for single module projects. I'm also using com.graphql-java:graphql-java-spring-boot-starter-webmvc:1.0in my dependencies plus a few of the regular sping boot dependencies, so my set up isn't completely vanilla.

我有一个多模块项目,所以单模块项目的配置可能不同。我还在com.graphql-java:graphql-java-spring-boot-starter-webmvc:1.0我的依赖项中使用了一些常规的 sping 启动依赖项,所以我的设置并不完全是普通的。