構建
本節介紹如何構建 Spring Shell 應用。
Starter 依賴
-
Spring Shell Starter 依賴
名稱 | 描述 |
---|---|
spring-shell-starter |
基礎 Spring Shell 模組 |
spring-shell-starter-jansi |
使用 JLine jansi 提供者 |
spring-shell-starter-jni |
使用 JLine jni 提供者 |
spring-shell-starter-jna |
使用 JLine jna 提供者 |
spring-shell-starter-ffm |
使用 JLine ffm 提供者 (需要 JDK22+) |
spring-shell-starter-test |
Spring Shell 測試支援 |
終端提供者
與程式執行的底層終端進行互動歷來是一個相對複雜的過程,儘管表面看起來一切都只是文字互動。
還記得那些舊式手動打字機或點陣印表機嗎?字元在游標所在位置列印,如果需要在不同位置列印,游標就需要移動。簡而言之,這就是當前終端模擬器的工作方式。
為了更好地訪問和理解現有的終端模擬器環境,JLine 可以透過自己的共享庫使用原生程式碼。JLine 檢測哪些提供者存在,然後選擇使用其中一個。傳統上有三種提供者:`jansi`、`jni` 和 `jna`,它們都應提供相同的功能。
我們的 starter 依賴可以用於專門選擇其中的一些 JLine 提供者。
FFM
隨著 `JDK22` 的釋出,*Foreign Function and Memory API* 從預覽版中正式推出,它旨在取代 `JNI`,提供更好、更安全的原生 API。
從 `3.4.x` 版本開始,我們增加了對使用 `JLine` 的 `ffm` 終端提供者編譯 Spring Shell 應用的支援。這顯然意味著應用需要在 `JDK22+` 環境下執行。新的 JDK 中間版本每 6 個月釋出一次,長期支援 (LTS) 版本每 2 年釋出一次。在 Spring Shell 能與 Spring Framework 對齊的現有 LTS 版本釋出之前,我們將使用最新的 JDK 版本。顯然,如果您選擇使用 `ffm`,這意味著您可能需要在不方便的時候升級您的 JDK。我們還受限於 JLine 本身用於編譯其 `ffm` 部分的 JDK 版本。
FFM 本身在使用某些部分時會導致 JVM 列印警告。這些警告對於終端應用來說顯然很煩人,因為它可能會干擾並造成一些混亂。在未來的 JDK 版本中,這些警告也將新增到舊的 JNI 模組中,並且在某個時候,這些警告將變為硬錯誤。使用者將被要求手動啟用這些原生“不安全”部分。
在命令列中,為此設定的 JVM 選項是
--enable-native-access=ALL-UNNAMED
如果您有一個 Jar 檔案,您可以在其 `META-INF/MANIFEST.MF` 中包含此設定。
Enable-Native-Access: ALL-UNNAMED
可以在構建過程中新增,例如在使用 Gradle 時
tasks.named("bootJar") {
manifest {
attributes 'Enable-Native-Access': 'ALL-UNNAMED'
}
}
至於在 JDK 中啟用原生部分,JLine 一直積極主動,已經對此進行了檢查,如果原生訪問未啟用,它將丟擲錯誤。 |
原生支援
將 *Spring Shell* 應用編譯為 *GraalVM* 二進位制檔案的支援主要來自 *Spring Framework* 和 *Spring Boot*,其中此功能稱為 *AOT*。AOT (Ahead of Time) 意味著應用上下文在編譯時就已準備好,以便進行 *GraalVM* 生成。
在 Spring Framework 和 Spring Boot 的 *AOT* 功能基礎上,*Spring Shell* 擁有自己的 *GraalVM* 配置,提供關於二進位制檔案中應包含哪些內容的提示。通常問題來自尚不包含 *GraalVM* 相關配置或配置不完整的第三方庫。
需要使用 *GraalVM Reachability Metadata Repository*,它為第三方庫提供了一些缺失的提示。您還需要安裝 *GraalVM* 並將 `JAVA_HOME` 指向它。 |
對於 *Gradle*,新增 graalvm 的原生外掛並配置元資料倉庫。
plugins {
id 'org.graalvm.buildtools.native' version '0.9.16'
}
graalvmNative {
metadataRepository {
enabled = true
}
}
使用 ./gradlew nativeCompile
執行 Gradle 構建時,您應該在 build/native/nativeCompile
目錄下獲得二進位制檔案。
對於 Maven
,使用 spring-boot-starter-parent
作為父專案,您將獲得一個 native
profile,可用於編譯。您需要配置元資料倉庫
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<configuration>
<metadataRepository>
<enabled>true</enabled>
</metadataRepository>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
如果您依賴 spring-boot-starter-parent ,它會管理 native-maven-plugin 的版本,並保持最新。 |
使用 ./mvnw native:compile -Pnative
執行 Maven 構建時,您應該在 target
目錄下獲得二進位制檔案。
如果一切順利,可以直接執行此二進位制檔案,而無需透過 JVM 執行 Boot 應用的 Jar 檔案。