构建
本节介绍如何构建 Spring Shell 应用程序。
启动器
-
Spring Shell 启动器
| 名称 | 描述 |
|---|---|
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 检测哪些提供者存在,然后选择使用哪一个。传统上,有 3 个提供者:jansi、jni 和 jna,它们都应该提供相同的功能。
我们的启动器可以用于专门选择其中一些 JLine 提供者。
FFM
随着 JDK22 的发布,外部函数和内存 API (Foreign Function and Memory API) 从预览版中脱颖而出,它有望取代 JNI,提供更好、更安全的本地 API。
从 3.4.x 开始,我们增加了对使用 JLine ffm 终端提供者编译 Spring Shell 应用程序的支持。这显然意味着应用程序需要在 JDK22+ 上运行。每 6 个月发布一个新的 JDK 中间版本,每 2 年发布一个长期支持 (LTS) 版本。在 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。提前编译意味着在编译时准备好应用程序上下文,以便进行 GraalVM 生成。
在框架的 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 配置文件,可用于执行原生编译。您需要配置元数据存储库
<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 执行引导应用程序 jar。