打包可执行归档文件
该插件可以创建包含应用程序所有依赖项的可执行归档文件(jar 文件和 war 文件),然后可以使用 java -jar
运行。
打包可执行 Jar 文件
可以使用bootJar
任务构建可执行的jar文件。当应用java
插件时,会自动创建此任务,它是一个BootJar
的实例。assemble
任务会自动配置为依赖于bootJar
任务,因此运行assemble
(或build
)也会运行bootJar
任务。
打包可执行的War文件
可以使用bootWar
任务构建可执行的war文件。当应用war
插件时,会自动创建此任务,它是一个BootWar
的实例。assemble
任务会自动配置为依赖于bootWar
任务,因此运行assemble
(或build
)也会运行bootWar
任务。
打包可执行且可部署的War文件
可以打包一个war文件,使其可以使用java -jar
执行并部署到外部容器中。为此,应将嵌入式servlet容器依赖项添加到providedRuntime
配置中,例如
-
Groovy
-
Kotlin
dependencies {
implementation('org.springframework.boot:spring-boot-starter-web')
providedRuntime('org.springframework.boot:spring-boot-starter-tomcat')
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
}
这确保它们被打包到war文件的WEB-INF/lib-provided
目录中,在那里它们不会与外部容器自己的类冲突。
providedRuntime 优于Gradle的compileOnly 配置,因为除了其他限制之外,compileOnly 依赖项不在测试类路径上,因此任何基于Web的集成测试都会失败。 |
打包可执行文件和普通归档文件
默认情况下,当配置bootJar
或bootWar
任务时,jar
或war
任务会被配置为使用plain
作为其归档分类器的约定。这确保了bootJar
和jar
或bootWar
和war
具有不同的输出位置,允许同时构建可执行归档文件和普通归档文件。
如果您希望可执行归档文件(而不是普通归档文件)使用分类器,请配置分类器,如下例中jar
和bootJar
任务所示
-
Groovy
-
Kotlin
tasks.named("bootJar") {
archiveClassifier = 'boot'
}
tasks.named("jar") {
archiveClassifier = ''
}
tasks.named<BootJar>("bootJar") {
archiveClassifier.set("boot")
}
tasks.named<Jar>("jar") {
archiveClassifier.set("")
}
或者,如果您希望根本不构建普通归档文件,请禁用其任务,如下例中jar
任务所示
-
Groovy
-
Kotlin
tasks.named("jar") {
enabled = false
}
tasks.named<Jar>("jar") {
enabled = false
}
创建原生镜像时,请勿禁用jar 任务。有关详细信息,请参阅#33238。 |
配置可执行归档文件的打包
BootJar
和BootWar
任务分别是Gradle的Jar
和War
任务的子类。因此,打包jar或war时可用的所有标准配置选项在打包可执行jar或war时也可用。还提供了一些特定于可执行jar和war的配置选项。
配置主类
默认情况下,可执行归档文件的主类将通过在主源集的输出中查找具有public static void main(String[])
方法的类来自动配置。
也可以使用任务的mainClass
属性显式配置主类
-
Groovy
-
Kotlin
tasks.named("bootJar") {
mainClass = 'com.example.ExampleApplication'
}
tasks.named<BootJar>("bootJar") {
mainClass.set("com.example.ExampleApplication")
}
或者,可以使用Spring Boot DSL的mainClass
属性在项目范围内配置主类名称
-
Groovy
-
Kotlin
springBoot {
mainClass = 'com.example.ExampleApplication'
}
springBoot {
mainClass.set("com.example.ExampleApplication")
}
如果已应用application
插件,则必须配置其mainClass
属性,并且可以用于相同目的
-
Groovy
-
Kotlin
application {
mainClass = 'com.example.ExampleApplication'
}
application {
mainClass.set("com.example.ExampleApplication")
}
最后,可以在任务的清单上配置Start-Class
属性
-
Groovy
-
Kotlin
tasks.named("bootJar") {
manifest {
attributes 'Start-Class': 'com.example.ExampleApplication'
}
}
tasks.named<BootJar>("bootJar") {
manifest {
attributes("Start-Class" to "com.example.ExampleApplication")
}
}
如果主类是用Kotlin编写的,则应使用生成的Java类的名称。默认情况下,这是Kotlin类名称,并在其后添加了Kt 后缀。例如,ExampleApplication 变为ExampleApplicationKt 。如果使用@JvmName 定义了其他名称,则应使用该名称。 |
包含仅开发依赖项
默认情况下,developmentOnly
配置中声明的所有依赖项都将从可执行jar或war中排除。
如果要将developmentOnly
配置中声明的依赖项包含在归档文件中,请配置其任务的类路径以包含该配置,如下例中bootWar
任务所示
-
Groovy
-
Kotlin
tasks.named("bootWar") {
classpath configurations.developmentOnly
}
tasks.named<BootWar>("bootWar") {
classpath(configurations["developmentOnly"])
}
配置需要解压的库
大多数库在嵌套在可执行归档文件中时可以直接使用,但是某些库可能会出现问题。例如,JRuby包含其自己的嵌套jar支持,该支持假设jruby-complete.jar
始终直接在文件系统上可用。
为了处理任何有问题的库,可以将可执行归档文件配置为在运行可执行归档文件时将特定嵌套jar解压到临时目录。可以使用与源jar文件绝对路径匹配的Ant风格模式来识别需要解压的库
-
Groovy
-
Kotlin
tasks.named("bootJar") {
requiresUnpack '**/jruby-complete-*.jar'
}
tasks.named<BootJar>("bootJar") {
requiresUnpack("**/jruby-complete-*.jar")
}
为了获得更多控制,还可以使用闭包。闭包传递一个FileTreeElement
,并应返回一个boolean
值,指示是否需要解压。
使归档文件完全可执行
Spring Boot提供了对完全可执行归档文件支持。通过在前面添加一个知道如何启动应用程序的shell脚本,可以使归档文件完全可执行。在类Unix平台上,此启动脚本允许直接运行归档文件,就像任何其他可执行文件一样,或者将其安装为服务。
目前,某些工具不接受此格式,因此您可能无法始终使用此技术。例如,jar -xf 可能会静默地无法提取已完全可执行的jar或war文件。建议您仅在打算直接执行它时才启用此选项,而不是使用java -jar 运行它或将其部署到servlet容器中。 |
要使用此功能,必须启用启动脚本的包含
-
Groovy
-
Kotlin
tasks.named("bootJar") {
launchScript()
}
tasks.named<BootJar>("bootJar") {
launchScript()
}
这会将Spring Boot的默认启动脚本添加到归档文件中。默认启动脚本包含几个具有合理默认值的属性。可以使用properties
属性自定义这些值
-
Groovy
-
Kotlin
tasks.named("bootJar") {
launchScript {
properties 'logFilename': 'example-app.log'
}
}
tasks.named<BootJar>("bootJar") {
launchScript {
properties(mapOf("logFilename" to "example-app.log"))
}
}
如果默认启动脚本不满足您的需求,则可以使用script
属性提供自定义启动脚本
-
Groovy
-
Kotlin
tasks.named("bootJar") {
launchScript {
script = file('src/custom.script')
}
}
tasks.named<BootJar>("bootJar") {
launchScript {
script = file("src/custom.script")
}
}
使用PropertiesLauncher
要使用PropertiesLauncher
启动可执行jar或war,请配置任务的清单以设置Main-Class
属性
-
Groovy
-
Kotlin
tasks.named("bootWar") {
manifest {
attributes 'Main-Class': 'org.springframework.boot.loader.launch.PropertiesLauncher'
}
}
tasks.named<BootWar>("bootWar") {
manifest {
attributes("Main-Class" to "org.springframework.boot.loader.launch.PropertiesLauncher")
}
}
打包分层Jar或War
默认情况下,bootJar
任务构建的归档文件分别在BOOT-INF/classes
和BOOT-INF/lib
中包含应用程序的类和依赖项。类似地,bootWar
构建的归档文件在WEB-INF/classes
中包含应用程序的类,在WEB-INF/lib
和WEB-INF/lib-provided
中包含依赖项。对于需要从jar内容构建docker镜像的情况,能够进一步分离这些目录非常有用,以便可以将它们写入不同的层。
分层jar使用与常规引导打包jar相同的布局,但包含一个描述每个层的附加元数据文件。
默认情况下,定义以下层
-
版本不包含
SNAPSHOT
的任何非项目依赖项的dependencies
。 -
jar加载器类的
spring-boot-loader
。 -
版本包含
SNAPSHOT
的任何非项目依赖项的snapshot-dependencies
。 -
项目依赖项、应用程序类和资源的
application
。
层的顺序很重要,因为它决定了应用程序的一部分发生变化时,以前层被缓存的可能性。默认顺序为dependencies
、spring-boot-loader
、snapshot-dependencies
、application
。应首先添加不太可能更改的内容,然后添加更可能更改的层。
要禁用此功能,您可以按照以下方式进行
-
Groovy
-
Kotlin
tasks.named("bootJar") {
layered {
enabled = false
}
}
tasks.named<BootJar>("bootJar") {
layered {
enabled.set(false)
}
}
创建分层jar或war时,spring-boot-jarmode-tools
jar将作为依赖项添加到您的归档文件中。使用类路径上的此jar,您可以以特殊模式启动应用程序,该模式允许引导代码运行与您的应用程序完全不同的内容,例如,提取层的内容。如果要排除此依赖项,可以按照以下方式进行
-
Groovy
-
Kotlin
tasks.named("bootJar") {
includeTools = false
}
tasks.named<BootJar>("bootJar") {
includeTools.set(false)
}
自定义层配置
根据您的应用程序,您可能希望调整层的创建方式并添加新的层。
这可以通过描述如何将jar或war分成层以及这些层的顺序的配置来完成。以下示例显示了如何显式定义上述默认排序
-
Groovy
-
Kotlin
tasks.named("bootJar") {
layered {
application {
intoLayer("spring-boot-loader") {
include "org/springframework/boot/loader/**"
}
intoLayer("application")
}
dependencies {
intoLayer("application") {
includeProjectDependencies()
}
intoLayer("snapshot-dependencies") {
include "*:*:*SNAPSHOT"
}
intoLayer("dependencies")
}
layerOrder = ["dependencies", "spring-boot-loader", "snapshot-dependencies", "application"]
}
}
tasks.named<BootJar>("bootJar") {
layered {
application {
intoLayer("spring-boot-loader") {
include("org/springframework/boot/loader/**")
}
intoLayer("application")
}
dependencies {
intoLayer("application") {
includeProjectDependencies()
}
intoLayer("snapshot-dependencies") {
include("*:*:*SNAPSHOT")
}
intoLayer("dependencies")
}
layerOrder.set(listOf("dependencies", "spring-boot-loader", "snapshot-dependencies", "application"))
}
}
layered
DSL使用三个部分定义
-
application
闭包定义如何对应用程序类和资源进行分层。 -
dependencies
闭包定义如何对依赖项进行分层。 -
layerOrder
方法定义层写入的顺序。
嵌套的intoLayer
闭包用于application
和dependencies
部分中,以声明层的内容。这些闭包按其定义的顺序(从上到下)进行评估。任何未被较早的intoLayer
闭包声明的内容仍可供后续闭包考虑。
intoLayer
闭包使用嵌套的include
和exclude
调用来声明内容。application
闭包对include/exclude参数使用Ant风格的路径匹配。dependencies
部分使用group:artifact[:version]
模式。它还提供了includeProjectDependencies()
和excludeProjectDependencies()
方法,可用于包含或排除项目依赖项。
如果未进行include
调用,则所有内容(未被较早的闭包声明)都将被视为有效。
如果未进行exclude
调用,则不应用任何排除。
查看上面示例中的dependencies
闭包,我们可以看到第一个intoLayer
将为application
层声明所有项目依赖项。下一个intoLayer
将为snapshot-dependencies
层声明所有SNAPSHOT依赖项。第三个也是最后一个intoLayer
将为dependencies
层声明任何剩余内容(在这种情况下,任何不是项目依赖项或SNAPSHOT的依赖项)。
application
闭包具有类似的规则。首先为spring-boot-loader
层声明org/springframework/boot/loader/**
内容。然后为application
层声明任何剩余的类和资源。
intoLayer 闭包添加的顺序通常与层写入的顺序不同。因此,必须始终调用 layerOrder 方法,并且必须涵盖 intoLayer 调用引用的所有层。 |