构建
此部分介绍了如何构建一个Spring Shell 应用程序。
Starters
-
Spring ShellStarters
| 姓名 | 描述 |
|---|---|
spring-shell-starter |
基本的 Spring 命令行模块 |
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 测试支持 |
所有 Spring Shell 资源包都会导入 spring-boot-starter,因此在使用 Spring Shell 资源包时无需再单独导入 spring-boot-starter。
终端提供商
传统上,与程序运行所在的底层终端进行交互是一个相对复杂的过程,尽管看起来好像并没有发生太多事情,因为一切都是文本。
还记得那些老式的手动打字机或矩阵打印机吗? 在一个字符被打印之后,光标需要移动 以在不同的位置进行打印。简单来说,这就是当前终端仿真程序的工作方式。
要更好地访问和理解现有的终端仿真器环境,
JLine 可以通过其自身的共享库使用本地代码。JLine 会检测哪些提供者存在,然后选择使用哪个。
传统上,有三种提供者,jansi、jni 和 jna,它们应该都提供相同的功能。
我们的starter可以用于特别挑选一些这些JLine提供的组件。
FFM
With JDK22 a Foreign Function and Memory API came out from a preview
which is supposed to be a replacement for JNI providing much better
and safer native API.
从3.4.x版本开始,我们增加了对使用JLine和ffm终端提供者的Spring Shell应用程序的支持。这显然意味着应用程序需要在JDK22+下运行。每隔6个月会有一次新的JDK中间版发布,每两年会有一个长期支持(LTS)版本。直到有现有的LTS版本之前,Spring Shell可以与Spring Framework对齐时,我们将使用最新的JDK发布版。这显然意味着如果你选择使用ffm,你可能需要在不便利的时间升级你的JDK。我们也受限于JLine本身使用的JDK版本。
ffm部分。
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。Ahead of Time 意味着在编译期间准备应用程序上下文,以便为 GraalVM 生成做准备。
Building atop of AOT features from a framework Spring Shell has its own GraalVM configuration providing hints what should exist in a binary. Usually trouble comes from 3rd party libraries which doesn’t yet contain GraalVM related configurations or those configurations are incomplete.
必须使用 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
版本,并保持其更新。 |
当使用 Maven 构建时,如果参数为 ./mvnw native:compile -Pnative,你应该会在 target 目录下得到二进制文件。
如果一切顺利,这个二进制文件可以直接运行,而不是通过JVM执行启动应用的jar包。
| 作为从v4.0.0开始,声明式的基于注解的命令注册不支持原生编译,当前仅支持通过编程方式定义命令。 |