对于最新的稳定版本,请使用 Spring Boot 3.4.0! |
打包可执行存档文件
该插件可以创建包含应用程序所有依赖项的可执行存档(jar 文件和 war 文件),然后可以使用java -jar
.
打包可执行 Jar
可执行 jar 可以使用bootJar
任务。
当java
plugin 的实例,并且是BootJar
.
这assemble
task 会自动配置为依赖于bootJar
任务如此运行assemble
(或build
) 也会运行bootJar
任务。
打包可执行 Wars
可执行 wars 可以使用bootWar
任务。
当war
plugin 的实例,并且是BootWar
.
这assemble
task 会自动配置为依赖于bootWar
任务如此运行assemble
(或build
) 也会运行bootWar
任务。
打包可执行和可部署的 War
可以打包 war 文件,以便可以使用java -jar
并部署到外部容器。
为此,应将嵌入式 servlet 容器依赖项添加到providedRuntime
configuration,例如:
-
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 依赖项不在测试 Classpath 上,因此任何基于 Web 的集成测试都将失败。 |
打包可执行存档和普通存档
默认情况下,当bootJar
或bootWar
任务配置后,该jar
或war
任务配置为使用plain
作为其档案分类器的约定。
这可确保bootJar
和jar
或bootWar
和war
具有不同的输出位置,从而允许同时构建 Executable Archive 和 Plain Archive。
如果您希望可执行存档(而不是普通存档)使用分类器,请按照以下示例所示为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("")
}
或者,如果您希望根本不构建 plain 存档,请禁用其任务,如以下示例所示。jar
任务:
-
Groovy
-
Kotlin
tasks.named("jar") {
enabled = false
}
tasks.named<Jar>("jar") {
enabled = false
}
请勿禁用jar task 创建原生镜像时执行。
有关详细信息,请参阅 #33238。 |
配置可执行归档文件打包
这BootJar
和BootWar
tasks 是 Gradle 的Jar
和War
任务。
因此,打包 jar 或 war 时可用的所有标准配置选项在打包可执行 jar 或 war 时也可用。
还提供了许多特定于可执行 jar 和 war 的配置选项。
配置 Main 类
默认情况下,可执行存档的主类将通过查找具有public static void main(String[])
方法。
主类也可以使用任务的mainClass
财产:
-
Groovy
-
Kotlin
tasks.named("bootJar") {
mainClass = 'com.example.ExampleApplication'
}
tasks.named<BootJar>("bootJar") {
mainClass.set("com.example.ExampleApplication")
}
或者,可以使用mainClass
Spring Boot DSL 的属性:
-
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 那么应该使用那个 name。 |
包括仅限开发的依赖项
默认情况下,在developmentOnly
configuration 将从可执行的 jar 或 war 中排除。
如果要包含在developmentOnly
configuration 中,配置其任务的 Classpath 以包含配置,如以下示例所示。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
task 会构建一个存档,其中包含应用程序的类和依赖项BOOT-INF/classes
和BOOT-INF/lib
分别。
同样地bootWar
构建一个包含应用程序类的存档WEB-INF/classes
和依赖项WEB-INF/lib
和WEB-INF/lib-provided
.
对于需要从 jar 的内容构建 docker 镜像的情况,能够进一步分离这些目录以便将它们写入不同的层非常有用。
分层 jar 使用与常规引导打包 jar 相同的布局,但包含一个描述每个层的附加元数据文件。
默认情况下,定义了以下图层:
-
dependencies
对于其版本不包含SNAPSHOT
. -
spring-boot-loader
对于 jar 加载器类。 -
snapshot-dependencies
对于其版本包含SNAPSHOT
. -
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 将作为依赖项添加到您的存档中。
在 Classpath 上使用此 jar,您可以以特殊模式启动应用程序,该模式允许引导代码运行与应用程序完全不同的东西,例如,提取层的东西。
如果您希望排除此依赖项,可以通过以下方式进行:
-
Groovy
-
Kotlin
tasks.named("bootJar") {
includeTools = false
}
tasks.named<BootJar>("bootJar") {
includeTools.set(false)
}
自定义图层配置
根据您的应用程序,您可能希望调整层的创建方式并添加新层。
这可以使用描述如何将 jar 或 war 分成层以及这些层的顺序的配置来完成。 以下示例显示了如何显式定义上述默认 Sequences:
-
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
closure 定义应用程序类和资源的分层方式。 -
这
dependencies
closure 定义依赖项应该如何分层。 -
这
layerOrder
method 定义层的写入顺序。
嵌 套intoLayer
闭包用于application
和dependencies
部分以声明图层的内容。
这些 Closure 按照定义的顺序从上到下进行评估。
任何未被早期用户认领的内容intoLayer
closure 仍可供后续考虑。
这intoLayer
使用嵌套的 Closure 声明内容include
和exclude
调用。
这application
closure 对 include/exclude 参数使用 Ant 样式的路径匹配。
这dependencies
部分用途group:artifact[:version]
模式。
它还提供includeProjectDependencies()
和excludeProjectDependencies()
可用于包含或排除项目依赖项的方法。
如果没有include
调用,则考虑所有内容(未被早期 Close 认领)。
如果没有exclude
调用,则不会应用任何排除项。
查看dependencies
closure 中,我们可以看到第一个intoLayer
将声明application
层。
下一个intoLayer
将声明snapshot-dependencies
层。
第三次也是最后一次intoLayer
将声明dependencies
层。
这application
closure 也有类似的规则。
首次认领org/springframework/boot/loader/**
content 的spring-boot-loader
层。
然后为application
层。
订单intoLayer 添加闭包通常与层的写入顺序不同。
因此,layerOrder 方法必须始终调用,并且必须覆盖intoLayer 调用。 |