1. 引言
在本教程中,我們將探討如何使用 spring-boot-thin-launcher 項目將 Spring Boot 項目構建為薄 JAR 文件。
Spring Boot 以其“胖” JAR 部署而聞名,其中一個可執行的工件包含應用程序代碼和所有依賴項。
Boot 也被廣泛用於開發微服務。這有時與“胖” JAR 方法相悖,因為在許多工件中重複包含相同的依賴項可能會造成資源浪費。
2. 先決條件
首先,我們需要一個 Spring Boot 項目。 在本文中,我們將探討 Maven 構建和 Gradle 構建的常見配置。
不可能涵蓋市場上所有的構建系統和構建配置,但我們希望能夠涵蓋足夠多的通用原則,以便您能夠將其應用於您自己的特定設置。
2.1. Maven 項目
在以 Maven 構建的 Boot 項目中,我們應該在項目的 <em pom.xml </em > 文件、其父項目或其祖先項目中配置 Spring Boot Maven 插件:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>Spring Boot 依賴的版本通常通過使用 BOM 或從父 POM 繼承來確定,如我們在參考項目中使用的。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<relativePath/>
</parent>2.2. Gradle 項目
在使用 Gradle 構建的 Boot 項目中,我們將擁有 Boot Gradle 插件:
buildscript {
ext {
springBootPlugin = 'org.springframework.boot:spring-boot-gradle-plugin'
springBootVersion = '3.1.5'
}
repositories {
mavenCentral()
}
dependencies {
classpath("${springBootPlugin}:${springBootVersion}")
}
}
// elided
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
springBoot {
mainClassName = 'com.baeldung.DemoApplication'
}請注意,本文檔將僅考慮 Boot 2.x 及更高版本項目。Thin Launcher 也支持較早版本,但需要略微不同的 Gradle 配置,為了簡化起見,我們已省略了該配置詳情。請參閲項目的主頁以獲取更多信息。
3. 如何創建瘦 JAR 文件?
Spring Boot Thin Launcher 是一個小型庫,它從打包存檔中包含的文件讀取應用程序的依賴項,從 Maven 倉庫下載它們,然後啓動應用程序的主類。因此,當我們使用該庫構建項目時,我們會得到包含我們代碼的 JAR 文件、列出其依賴項的文件以及執行上述任務的主類。
當然,事情比我們的簡化解釋要複雜一些;稍後我們將深入探討一些主題。
4. 基本用法
現在我們來看如何從我們的 Spring Boot 應用程序中構建“瘦” JAR 文件。
我們將使用常規命令啓動應用程序:<em java -jar <my-app-1.0.jar>, </strong>,並可以包含用於控制瘦啓動器的可選命令行參數。 我們將在後面的章節中看到一些參數;項目的主頁包含完整的列表。
4.1. Maven 項目
在 Maven 項目中,我們需要修改 Boot 插件的聲明(參見第 2.1 節),以包含對自定義“thin”佈局的依賴。
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<!-- The following enables the "thin jar" deployment option. -->
<dependency>
<groupId>org.springframework.boot.experimental</groupId>
<artifactId>spring-boot-thin-layout</artifactId>
<version>1.0.11.RELEASE</version>
</dependency>
</dependencies>
</plugin>啓動器將從 pom.xml 文件中讀取依賴項,該文件由 Maven 存儲在生成的 JAR 文件中的 META-INF/maven 目錄下。
我們將按照正常流程進行構建,例如使用 mvn install 。
如果我們需要能夠生成瘦構建和胖構建(例如在具有多個模塊的項目中),我們可以通過在專用 Maven 配置文件中聲明自定義佈局來實現。
4.2. Maven 與依賴:thin.properties
我們還可以讓 Maven 生成 thin.properties 文件,除了 pom.xml 之外。在這種情況下,該文件將包含所有依賴項的完整列表,包括傳遞依賴項,並讓啓動器優先使用它,而不是 pom.xml。
用於執行此操作的 mojo(插件)是 spring-boot-thin-maven-plugin:properties,默認情況下,它會將 thin.properties 文件輸出到 src/main/resources/META-INF,但可以使用 thin.output 屬性指定其位置:
$ mvn org.springframework.boot.experimental:spring-boot-thin-maven-plugin:properties -Dthin.output=.請注意,目標目錄必須存在,即使我們使用了默認目錄。
4.3. Gradle 項目
在 Gradle 項目中,我們添加一個專門的插件:
buildscript {
ext {
//...
thinPlugin = 'org.springframework.boot.experimental:spring-boot-thin-gradle-plugin'
thinVersion = '1.0.11.RELEASE'
}
//...
dependencies {
//...
classpath("${thinPlugin}:${thinVersion}")
}
}
//elided
apply plugin: 'maven'
apply plugin: 'org.springframework.boot.experimental.thin-launcher'為了獲得精簡的構建,我們將告訴 Gradle 執行 thinJar 任務:
~/projects/baeldung/spring-boot-gradle $ ./gradlew thinJar4.4. Gradle 和依賴項:<em pom.xml</em>>
在上一節的代碼示例中,我們聲明瞭 Thin Launcher 插件,以及我們在“先決條件”部分已經見過的 Maven 和依賴管理插件。
這是因為,正如我們在之前看到的 Maven 案例中一樣,該 Artifact 將包含並利用一個 <em pom.xml</em>> 文件,該文件列出了應用程序的依賴項。 <em pom.xml</em>> 文件由一個名為 <em thinPom</em>> 的任務生成,該任務是任何 jar 任務的隱式依賴。
我們可以使用專門的任務自定義生成的 <em pom.xml</em>> 文件。 在這裏,我們將簡單地複製 Thin 插件自動執行的功能:
task createPom {
def basePath = 'build/resources/main/META-INF/maven'
doLast {
pom {
withXml(dependencyManagement.pomConfigurer)
}.writeTo("${basePath}/${project.group}/${project.name}/pom.xml")
}
}為了使用我們的自定義 pom.xml 文件,我們將上述任務添加到 jar 任務的依賴項中:
bootJar.dependsOn = [createPom]4.5. Gradle 和依賴:thin.properties</h3
我們還可以讓 Gradle 生成 thin.properties 文件而不是 pom.xml,就像我們之前使用 Maven 時所做的那樣。
生成 thin.properties 文件的任務稱為 thinProperties,默認情況下它未啓用。我們可以將其作為 jar 任務的依賴項添加:
bootJar.dependsOn = [thinProperties]5. 存儲依賴項
使用薄罐的主要目的是避免將依賴項與應用程序打包在一起。然而,依賴項並不會憑空消失,它們只是存儲在其他地方。
Thin Launcher 使用 Maven 基礎設施來解決依賴項,因此:
- 它會檢查本地 Maven 倉庫,默認情況下位於 ~/.m2/repository,但也可以移動到其他位置;
- 然後,它會從 Maven Central(或任何其他配置的倉庫)下載缺失的依賴項;
- 最後,它會將它們緩存到本地倉庫中,以便下次運行應用程序時無需重新下載。
當然,下載階段是整個過程中的緩慢且容易出錯的部分,因為它需要通過互聯網訪問 Maven Central,或者訪問本地代理,我們都知道這些東西通常不可靠。
幸運的是,有各種方法可以將依賴項與應用程序(例如,在預打包的容器中用於雲部署)。
5.1. 在目標環境中運行應用程序進行預熱
最簡單的方法是使用預熱運行來緩存依賴項,即在目標環境中運行應用程序。正如前面所見,這會導致依賴項下載並緩存到本地 Maven 倉庫中。如果運行多個應用程序,倉庫將包含所有依賴項,且不會出現重複。
由於運行應用程序可能會產生未知的副作用,我們還可以執行“幹運行”操作,該操作僅解決和下載依賴項,而不會執行任何用户代碼:
$ java -Dthin.dryrun=true -jar my-app-1.0.jar請注意,根據 Spring Boot 的約定,您也可以通過命令行參數 -Dthin.dryrun 或系統屬性 THIN_DRYRUN 來設置 -Dthin.dryrun 屬性。 任何非 false 的值都將指示 Thin Launcher 執行預執行操作。
5.2. 構建過程中打包依賴項
另一種選擇是在構建過程中收集依賴項,而不將它們打包到 JAR 文件中。然後,我們可以將它們作為部署過程的一部分複製到目標環境。
這通常更簡單,因為它不需要在目標環境中運行應用程序。但是,如果我們在部署多個應用程序,則需要合併它們的依賴項,手動或使用腳本。
Thin Plugin for Maven 和 Gradle 在構建過程中打包依賴項的格式與 Maven 本地倉庫相同:
root/
repository/
com/
net/
org/
...事實上,我們可以使用 Thin Launcher 將應用程序指向任何這樣的目錄(包括本地 Maven 倉庫)在運行時,通過 <em >thin.root </em >屬性:。
$ java -jar my-app-1.0.jar --thin.root=my-app/deps我們可以安全地通過將多個此類目錄相互覆蓋來合併它們,從而獲得包含所有必要依賴項的 Maven 倉庫。
5.3. 使用 Maven 打包依賴項
為了讓 Maven 為我們打包依賴項,我們使用 <em resolve</em> 目標,該目標位於 <em spring-boot-thin-maven-plugin</em> 中。我們可以手動或自動地在我們的 <em pom.xml</em> 中調用它:
<plugin>
<groupId>org.springframework.boot.experimental</groupId>
<artifactId>spring-boot-thin-maven-plugin</artifactId>
<version>${thin.version}</version>
<executions>
<execution>
<!-- Download the dependencies at build time -->
<id>resolve</id>
<goals>
<goal>resolve</goal>
</goals>
<inherited>false</inherited>
</execution>
</executions>
</plugin>在完成項目構建後,我們會在 target/thin/root/ 目錄下找到我們之前討論的結構。
5.4. 使用 Gradle 打包依賴項
如果我們在使用 Gradle 並且使用了 thin-launcher 插件,我們有一個 thinResolve 任務可用。該任務會將應用程序及其依賴項保存到 build/thin/root/ 目錄中,類似於上一節 Maven 插件的功能:
$ gradlew thinResolve6. 結論與進一步閲讀
在本文中,我們探討了如何創建輕量級 JAR 包。我們還看到了如何使用 Maven 基礎設施下載和存儲依賴項。
輕量級啓動器的 主頁 提供了針對諸如 Heroku 雲部署等場景的更多 HOW-TO 指南,以及支持的所有命令行參數的完整列表。
所有 Maven 示例和代碼片段的實現可以在 GitHub 項目 中找到——作為一個 Maven 項目,因此應該很容易導入和運行。