在过去的 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 应用程序。 双重哎!!!
所有这些负面情绪都被一些有趣的发现和一些仔细的思考所克服
- 配置信息可以作为元数据打包在元数据表中,最终用户可以选择“配置”来选择该表。
- 应用程序可以相当容易地检查其版本号与当前分发的版本号,并拒绝运行,或者至少向任何运行过时版本的用户抱怨。
- 应用程序可以与使用 Open JDK 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\*
- 使用上述命令的输出,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 条评论