在过去的 15 年左右,我所在的组织一直使用 Java 网络启动协议 (JNLP) 在内部向其用户分发 Java Swing 桌面应用程序。
为了访问 Java Swing 应用程序,用户必须安装特定版本的 Java 平台标准版 (Java SE),其中包含对 JNLP 的支持。 当他们想要使用该应用程序时,他们会点击组织内联网中的链接,Java Web Start (javaws) 程序将下载链接处的 XML,解释它,下载当前版本的应用程序(如果需要),并运行它,同时管理应用程序运行的安全沙箱。 换句话说,这是一种很好、低仪式的方式,可以将完全配置的应用程序分发到每个人的桌面。
然而,由于 JNLP 不再是 Java SE 的一部分(从版本 11 开始),该组织面临一个决定:停止使用 JNLP 作为 Java SE 的一部分,或者放弃其与 Java SE 版本保持合理同步的策略。 这个听起来相对简单的选择,由于各种原因,结果变得有些复杂。
选项 1:保留当前的 Java SE 并寻找 JNLP 的替代品
IcedTea-Web 是一个提供 JNLP 功能的开源项目。 这意味着一个两步预配置过程:1) 安装 Java SE,以及 2) 安装 IcedTea-Web,这将增加客户端维护。 不幸的是,当我们在评估选项时,没有与 Java 11 兼容的 IcedTea-Web 设施,因此这意味着使用 Java 8。 然而,Java SE 8 将于 2019 年 3 月达到生命周期终止,因此我们将不得不从 OpenJDK 8 创建 Java 8 运行时环境,以便在客户端机器上安装,并转向更手动地跟踪 OpenJDK 8 更新的过程。 这些方法似乎都不太有吸引力。
选项 2:远离 JNLP
起初,这种方法似乎是最糟糕的情况——我们需要修改应用程序以某种其他方式提供配置信息; JNLP 中所有好的自动更新功能都将被丢弃; 我们需要某种按工作站的安装过程。 呜呼! 或者我们可以将用户社区喜欢的现有胖客户端应用程序重写为 Web 应用程序。 双重呜呼!!!
所有这些消极情绪都被一些有趣的发现和一点仔细的思考所克服
- 配置信息可以打包为元数据表中的元数据,最终用户可以选择该元数据作为“配置”。
- 应用程序可以相当容易地检查其版本号与当前分发的版本号,并拒绝运行,或者至少向任何运行过时版本的用户发出警告。
- 应用程序可以与使用 OpenJDK 11 中提供的 jdeps 和 jlink 命令创建的定制 Java 运行时一起打包,从而确保应用程序始终使用正确版本的 Java 运行。
- 整个安装和执行业务可以在客户端使用 Windows .cmd 文件处理,从而无需安装程序(也许有一天...)。
- 应用程序和定制的 Java 运行时分发仍然可以作为从内联网下载的内容来处理。
有了这些细节,细心的读者或许可以猜到……
选择的解决方案
最后,该组织决定放弃 JNLP,因为与维护现有的 JNLP 环境相比,最终用户管理量似乎相当简单明了。
以下是获得解决方案的详细过程
- 构建应用程序
- 该应用程序始终是使用在 Linux 桌面环境中运行的 NetBeans IDE 开发和维护的; 现在仍然如此,使用 OpenJDK 11(来自发行版)和 NetBeans 10(从 新的 Apache NetBeans 网站 下载)。
- 构建过程创建一个操作系统无关的 dist 文件夹,其中包含应用程序 .jar 文件和所有必需的库
- 定制 Java 11 运行时
- 不幸的是,没有办法定制跨平台 Java 运行时,所以我们需要一台中间 Windows 计算机——我们称之为 IWC。 (我要直接说,这是我们方法的主要缺点。)
- OpenJDK 11 预构建二进制文件安装在 IWC 上。
- 应用程序 dist 文件夹被复制到 IWC。
- 在 dist 文件夹中,来自 OpenJDK 11 的 jdeps 命令确定支持应用程序所需的 Java 运行时组件
jdeps --print-module-deps TheApplication.jar lib\*
- 使用上述命令的输出,来自 OpenJDK 11 的 jlink 命令(同样来自 OpenJDK 11)构建定制的运行时
jlink --no-header-files --no-man-pages --compress=2 \ --strip-debug –add-modules \ java.base,java.desktop,java.sql,java.security.jgss,java.xml \ --output customjre
- 此时,可以使用以下命令从此文件夹运行(测试)应用程序
.\customjre\bin\java -jar TheApplication.jar
- Install.cmd 和 RunTheApplication.cmd 文件被复制到 dist 文件夹中。
- 捆绑应用程序以进行分发
- 包含应用程序、.cmd 文件和定制运行时的 dist 文件夹被压缩并放在内联网服务器上; 指向 .zip 文件的链接允许用户下载它。
- 下载、安装和运行应用程序
- 用户导航到包含指向 .zip 文件的链接的页面。
- 单击链接下载 .zip 文件。
- 用户解压缩 .zip 文件,导航到 dist 文件夹,然后双击 Install.cmd。
- 当 Install.cmd 执行时,它将 dist 文件夹复制到用户计算机上的已知位置,并在用户的桌面上安装 RunTheApplication.cmd 链接。
- 用户需要具有某些权限才能安装应用程序。
- 用户无需在计算机上安装 Java SE。
应用程序已修改为
- 从数据库表中读取配置参数(组织将这些视为“项目参数”,因此用户正在“选择项目”)。
- 从本地和服务器上的 RELEASE_NOTES.TXT 中提取 VERSION=123 字符串,以确保版本匹配(如果版本不匹配,最终用户会受到骚扰)。
就是这样。 当然,可以使用安装程序而不是 .cmd 文件来获得“更专业”的安装体验。 也可以找到其他方法在 IWC 上安装 OpenJDK 11,IWC 甚至可以是虚拟机 (使其成为 VIWC)。 遗憾的是,jlink 命令没有 --target-platform 选项或许多其他改进,这些改进可能是根据部署环境的性质而需要的或必要的。
它的效果如何?
早期报告表明用户对结果感到满意,系统管理员不再负责监控已安装的 Java SE 版本。 至于支持该应用程序的人员,他对额外的构建步骤或多或少还可以接受——但宁愿处理两台机器,也不愿在他的漂亮的 System76 笔记本电脑上运行 VIWC。
4 条评论