封裝可執行歸檔文件
此外掛程式可以建立包含應用程式所有依賴項的可執行歸檔文件 (jar 檔和 war 檔),然後可以使用 java -jar
執行。
封裝可執行 Jar
可執行 jar 可以使用 bootJar
任務來建置。當套用 java
外掛程式時,此任務會自動建立,並且是 BootJar
的一個實例。assemble
任務會自動組態為依賴 bootJar
任務,因此執行 assemble
(或 build
) 也會執行 bootJar
任務。
封裝可執行 War
可執行 war 可以使用 bootWar
任務來建置。當套用 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
目錄中,從而不會與外部容器自身的類別衝突。
相較於 Gradle 的 compileOnly 組態,providedRuntime 是更佳的選擇,因為除了其他限制之外,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
}
在建立 Native Images 時,請勿停用 jar 任務。有關詳細資訊,請參閱 #33238。 |
組態可執行歸檔文件封裝
BootJar
和 BootWar
任務分別是 Gradle 的 Jar
和 War
任務的子類別。因此,封裝 jar 或 war 時可用的所有標準組態選項,在封裝可執行 jar 或 war 時也可用。還提供許多特定於可執行 jar 和 war 的組態選項。
組態 Main Class
預設情況下,可執行歸檔文件的 main class 將會透過在主要來源集的輸出中尋找具有 public static void main(String[])
方法的類別來自動組態。
也可以使用任務的 mainClass
屬性明確組態 main class
-
Groovy
-
Kotlin
tasks.named("bootJar") {
mainClass = 'com.example.ExampleApplication'
}
tasks.named<BootJar>("bootJar") {
mainClass.set("com.example.ExampleApplication")
}
或者,可以使用 Spring Boot DSL 的 mainClass
屬性,在專案範圍內組態 main class 名稱
-
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")
}
最後,可以在任務的 manifest 上組態 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")
}
}
如果 main class 是以 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 解壓縮到臨時目錄。可以使用 Ant 樣式模式來識別需要解壓縮的函式庫,這些模式會比對來源 jar 檔的絕對路徑
-
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,請組態任務的 manifest 以設定 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 使用與常規 Boot 封裝 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 將會作為依賴項新增至您的歸檔文件。透過類別路徑上的此 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 呼叫引用的所有層。 |