如何使用 JRE 部署 JavaFX 11 桌面应用程序编写模块描述符建筑制作一个jmod连接分布跨建筑

2022-09-01 01:38:51

我有一个JavaFX(JDK 8)桌面业务应用程序,它使用Java Web Start进行部署。用户安装了 Java 8,只需转到 URL(我的 AWS Linux 服务器上的公有 URL),应用程序即可下载/启动(使用 Web Start)。我也可以通过将新的 JAR 部署到服务器来轻松更新应用程序。一切都很好。

但是,Oracle已经停止了Java 11的Web Start,并且在2018年3月的“Java客户端路线图更新”白皮书中,他们建议将JRE与应用程序捆绑在一起(“因此,应用程序与独立JRE分开分发的概念正在迅速消失。我不能指望我的用户留在Java 8 for Web Start,即使他们仍然保持在8,Oracle也需要许可证才能继续使用Java 8(我没有,可能非常昂贵,无论如何我都希望与社区一起转向JavaFX 11和OpenJDK)。

我想迁移到 JavaFX 11。我遵循了OpenJFX的“JavaFX11入门”(https://openjfx.io/openjfx-docs/),使用OpenJDK 11.0.1和Gluon的JavaFX SDK 11.0.1(在Netbeans 10vc2上),并且能够运行示例应用程序(在我看来,我应该能够很容易地将JavaFX 8代码移植到JavaFX 11)。

然而,这就是我被困在方向的地方。如何将其与 JRE 捆绑在一起并将其部署到我的最终用户(并提供应用程序更新)?有没有一个简单的方法(甚至是一个困难的方法,有一些方向/指南)?

我可以花费数百个小时在 JavaFX 11 中编写富有表现力、丰富且有用的桌面业务应用程序,但是我该怎么办呢?

部署工具包,如JWrapper,InstallAnywhere等,是否适合Java 11的新时代?Gluon/openjfx.io是否有我错过的建议或指南?我似乎无法从信誉良好的来源找到任何建议或指南,关于我们这些专注于编写前端代码的开发人员如何部署应用程序。

感谢您的任何帮助或指导。


答案 1

它现在的工作方式是,您将程序转换为模块,然后将其“链接”到所需的所有其他模块。

此链接过程的结果是所谓的图像。映像实际上是一个文件树,其中包括一个目录,其中包含一个或多个随时可运行的可执行文件。此树是您分发的内容,通常以 zip 或 tar.gz的形式分发。bin

步骤如下:

  1. 创建模块信息.java
  2. 使用模块路径而不是类路径进行编译
  3. 像往常一样从类中创建一个 jar
  4. 使用JDK的工具将jar转换为jmodjmod
  5. 将该 jmod 及其所依赖的模块链接到图像中

编写模块描述符

第一步是将应用程序转换为模块。至少,这需要在源代码树的顶部(即在空包中)创建一个。每个模块都有一个名称,该名称通常与包名称相同,但不必如此。因此,您的模块信息.java可能如下所示:module-info.java

module com.mcs75.businessapp {
    exports com.mcs75.desktop.businessapp;

    requires java.logging;
    requires transitive javafx.graphics;
    requires transitive javafx.controls;
}

建筑

生成时,根本不指定类路径。而是指定模块路径。

模块路径是目录的列表,而不是文件。毫不奇怪,每个目录都包含模块。JDK 的目录是隐式包含的。您需要包含的只是包含所需非 JDK 模块的目录。在你的情况下,这至少意味着Gluon的JavaFX:jmods

javac -Xlint -g -d build/classes --module-path /opt/gluon-javafx/lib \
    src/java/com/mcs75/desktop/businessapp/*.java

然后,您以通常的方式创建一个jar:

jar -c -f build/mybusinessapp.jar -C build/classes .

包含 module-info.class 的 jar 文件被视为模块化 jar。

制作一个jmod

创建 jmod 通常是一个简单的过程:

mkdir build/modules
jmod create --class-path build/mybusinessapp.jar \
    --main-class com.mcs75.desktop.businessapp.BusinessApplication \
    build/modules/mybusinessapp.jmod

连接

最后,使用 JDK 的命令来组装所有内容:jlink

jlink --output build/image \
    --module-path build/modules:/opt/gluon-javafx/lib \
    --add-modules com.mcs75.businessapp \
    --launcher MyBusinessApp=com.mcs75.businessapp

jlink创建一个最小的 JRE,它只包含显式添加的模块(以及这些显式模块所需的模块)。 是指定要添加的内容的必需选项。--add-modules

与其他 JDK 工具一样,指定包含模块的目录。--module-path

该选项使最终图像树在其目录中具有具有给定名称(等于之前的部分)的附加可执行脚本。因此,这意味着“创建一个名为MyBusinessApp的可执行文件,该可执行模块com.mcs75.businessapp。--launcherbinMyBusinessApp=com.mcs75.businessapp

由于该命令包含一个选项,因此 Java 将知道要执行什么,就像在清单中声明 Main-Class 属性一样。如果需要,还可以在选项中显式声明要执行的类。jmod create--main-class--launcher

分布

您要分发的是整个图像文件树的 zip 或 tar.gz。用户应运行的可执行文件位于映像的目录中。当然,您可以自由添加自己的可执行文件。您也可以自由地将其放入任何类型的安装程序中,只要保留映像树的结构即可。bin

未来的JDK将有一个打包工具,用于创建成熟的本机安装程序。从Java 14开始,JDK有一个jpackage工具,可以创建本机安装程序。例如:

jpackage -n MyBusinessApp --runtime-image build/image \
    -m com.mcs75.businessapp/com.mcs75.desktop.businessapp.BusinessApplication

-n指定程序的名称。 指定现有 jlink 图像的位置。 是 jlink'd 映像中要执行的模块和类,很像 in jlink 选项后面的部分。--runtime-image-m=--launcher

跨建筑

由于映像包含本机二进制文件,因此需要为每个平台创建一个映像。显然,一种选择是在Linux系统上构建映像,在Windows系统上再次构建映像,在Mac上再次构建映像,等等。

但是,您也可以使用和创建其他平台的映像,无论您在何处构建。jmodjlink

只需要几个额外的步骤。首先,您将需要用于其他平台的JDK。将它们下载为存档(zip或tar.gz),而不是安装程序,然后将它们解压缩到您选择的目录中。

每个 JDK 定义一个平台字符串。这通常采用<os>-<arch>的形式。平台是模块的属性;您可以通过检查该模块来查看任何JDK的平台:java.base

jmod describe path-to-foreign-jdk/jmods/java.base.jmod | grep '^platform'

使用以下选项将该平台字符串传递给 jmod 命令:--target-platform

mkdir build/modules
jmod create --target-platform windows-amd64 \
    --class-path build/mybusinessapp.jar \
    --main-class com.mcs75.desktop.businessapp.BusinessApplication \
    build/modules/mybusinessapp.jmod

最后,在链接时,您希望显式包含其他 JDK 的目录,因此 jlink 不会隐式包含自己的 JDK 模块:jmods

jlink --output build/image \
    --module-path path-to-foreign-jdk/jmods:build/modules:/opt/gluon-javafx-windows/lib \
    --add-modules com.mcs75.businessapp \
    --launcher MyBusinessApp=com.mcs75.businessapp

答案 2

为了使用IDE使事情变得更容易,我使用Intellij Idea;构建自动化,我使用gradle;和jlink插件,我使用坏蛋Jlink插件 - https://badass-jlink-plugin.beryx.org/releases/latest/#jpackageImage。然后,您可以轻松地使用jlink和jpackage。只是一个想法。


推荐