在本文中,我们将看到如何将旧但有用的旧版Java应用程序变成全新的Java Web Start(简称JWS)应用程序。
JWS是一种经常被忽略的技术,可以创造奇迹。 有了它,您可以像部署Web应用程序一样轻松地部署任何 Java应用程序:具有唯一的更新服务器端,并且您的应用程序仍在客户端运行,并且可以访问其所有资源。 JWS具有两个主要功能:将应用程序下载到客户端和启动所述应用程序。 从1.4版开始,这是Java Runtime Environment中可用的技术。
JWS基于JNLP格式的最特定的部署描述符。 该DD沿着服务器上应用程序的许多JAR发生。 尽管Sun没有发布DTD或XSD格式的模式,但JNLP文件是XML。 您可能会在网上找到一些人制作的模式。
为了通过JWS发布应用程序,您需要执行以下步骤。
步骤1:将您的代码用作网络资源
我向您出售了可以在网络上使用任何Java应用程序的方法。 这意味着您必须同时发布JAR本身和关联的JNLP。
-
/jnlp/@codebase
指定根目录所在的位置 -
/jnlp/@href
此根目录下的JNLP文件的名称 -
/jnlp/resources/jar/@href
到JAR的路径
<?xml version="1.0" encoding="utf-8"?>
<jnlpcodebase="http://blog.frankel.ch/demo"href="launch.jnlp">
<information>
<title> Legacy Application </title>
<vendor> Nicolas Frankel </vendor>
</information>
<resources>
<jarhref="myMainJar.jar"/>
</resources>
</jnlp>
/jnlp/information/title
和/jnlp/information/vendor
都是必需的,并将显示在JWS对话框菜单中。
步骤2:获取JRE版本
由于您将使您的应用程序可用,因此请问您自己,客户端计算机上将使用哪个版本。 本质上,这将涉及两件事:
-
/jnlp/@spec
指定JNLP XML格式的版本 -
/jnlp/resources/j2se/@version
所需的客户端JRE版本
<?xml version="1.0" encoding="utf-8"?>
<jnlpspec="1.5+"codebase="http://blog.frankel.ch/demo"href="launch.jnlp">
<information>
<title> Legacy Application </title>
<vendor> Nicolas Frankel </vendor>
</information>
<resources>
<j2seversion="1.5+"/>
<jarhref="myMainJar.jar"/>
</resources>
</jnlp>
查看两者如何可以使用加号来指示最低版本。
您甚至可以告诉JWS将浏览器重定向到JRE下载页面或自动下载。 两者都是通过JavaScript和HTML的组合来完成的。
步骤3:引用依赖库和主类
通常,有关主类(包含main方法的主类)和JAR依赖项的信息是在命令行上或在JAR的部署描述符中指定的。
在命令行上指定的信息:
java -cp myMainJar.jar;lib/myFirstDependency.jar;lib/mySecondDependency.jar ch.frankel.blog.jws.MainClass
MANIFEST.MF
指定的信息:
java -jar myMainJar.jar
JAR中的META-INF/MANIFEST.MF
:
Manifest-Version: 1.0
Class-Path: lib/myFirstDependency.jar lib/mySecondDependency.jar
Main-Class: ch.frankel.blog.jws.MainClass
首先要了解的是JWS忽略清单文件。 因此,无论哪种情况,您都必须在JNLP中手动告诉Java Web Start主类和您的依赖项。
<?xml version="1.0" encoding="utf-8"?>
<jnlpspec="1.5+"codebase="http://blog.frankel.ch/demo"href="launch.jnlp">
<information>
<title> Legacy Application </title>
<vendor> Nicolas Frankel </vendor>
</information>
<resources>
<j2seversion="1.5+"/>
<jarhref="myMainJar.jar"/>
<jarhref="lib/myFirstDependency.jar"/>
<jarhref="lib/mySecondDependency.jar"/>
</resources>
<application-descmain-class="ch.frankel.blog.jws.MainClass"/>
</jnlp>
注意,包含主类的JAR和从属JAR都是如何以相同的方式引用的。 lib文件夹仅供我使用:JWS不会根据JAR的位置进行区分。
步骤4:将系统属性传递给JVM
通常,系统属性是通过命令行传递给JVM的,如下所示:
java -Dch.frankel.firstProp -Dch.frankel.secondProp=aValue -jar myMainJar.jar
在JNLP中同样如此:
<?xml version="1.0" encoding="utf-8"?>
<jnlpspec="1.5+"codebase="http://blog.frankel.ch/demo"href="launch.jnlp">
<information>
<title> Legacy Application </title>
<vendor> Nicolas Frankel </vendor>
</information>
<resources>
<j2seversion="1.5+"/>
<propertyname="ch.frankel.firstProp"/>
<propertyname="ch.frankel.secondProp"value="aValue"/>
<jarhref="myMainJar.jar"/>
<jarhref="lib/myFirstDependency.jar"/>
<jarhref="lib/mySecondDependency.jar"/>
</resources>
<application-descmain-class="ch.frankel.blog.jws.MainClass"/>
</jnlp>
步骤5:将参数传递到您的应用程序
参数通过命令行传递到您的main方法,如下所示:
java -jar myMainJar.jar myFirstParam mySecondParam
在JNLP中同样如此:
<?xml version="1.0" encoding="utf-8"?>
<jnlpspec="1.5+"codebase="http://blog.frankel.ch/demo"href="launch.jnlp">
<information>
<title> Legacy Application </title>
<vendor> Nicolas Frankel </vendor>
</information>
<resources>
<j2seversion="1.5+"/>
<propertyname="ch.frankel.firstProp"/>
<propertyname="ch.frankel.secondProp"value="aValue"/>
<jarhref="myMainJar.jar"/>
<jarhref="lib/myFirstDependency.jar"/>
<jarhref="lib/mySecondDependency.jar"/>
</resources>
<application-descmain-class="ch.frankel.blog.jws.MainClass">
<argument> myFirstParam </argument>
<argument> mySecondParam </argument>
</application-desc>
</jnlp>
步骤6:签署JAR
Java Web Start应用程序应在沙箱中运行,因为它们是从Web上下载的,根据定义,所有资源都不安全。 如果您的应用程序不使用可能不安全的操作,那很好。 如果是这样,则必须在JNLP中明确要求特殊权限。 不安全的操作包括:文件访问,剪贴板使用等。
<?xml version="1.0" encoding="utf-8"?>
<jnlpspec="1.5+"codebase="http://blog.frankel.ch/demo"href="launch.jnlp">
<information>
<title> Legacy Application </title>
<vendor> Nicolas Frankel </vendor>
</information>
<resources>
<j2seversion="1.5+"/>
<propertyname="ch.frankel.firstProp"/>
<propertyname="ch.frankel.secondProp"value="aValue"/>
<security>
<all-permissions/>
</security>
<jarhref="myMainJar.jar"/>
<jarhref="lib/myFirstDependency.jar"/>
<jarhref="lib/mySecondDependency.jar"/>
</resources>
<application-descmain-class="ch.frankel.blog.jws.MainClass">
<argument> myFirstParam </argument>
<argument> mySecondParam </argument>
</application-desc>
</jnlp>
有一个大问题,那就是:您所有的JAR都必须使用相同的证书签名! 这意味着,如果引用已签名的JAR,则必须先将其取消签名,然后再使用唯一的证书对其进行签名。
如果这对您来说太麻烦了,那么您将需要更改代码的诉讼部分,并用对JNLP API的调用来替换它们。 在这种情况下,请告别您的应用程序在Web Start上下文之外运行的能力。 注意,API很小。
第7步:增强用户体验
快捷方式,启动屏幕,脱机运行的能力,Java Web Start可以提供所有这些。 以下JNLP将这些功能添加到上一个功能中:
<?xml version="1.0" encoding="utf-8"?>
<jnlpspec="1.5+"codebase="http://blog.frankel.ch/demo"href="launch.jnlp">
<information>
<title> Legacy Application </title>
<vendor> Nicolas Frankel </vendor>
<offline-allowed/>
<iconkind="splash"href="image/welcome.jpg"/>
<shortcutonline="false">
<desktop/>
<menusubmenu="frankel dot ch"/>
</shortcut>
</information>
<resources>
<j2seversion="1.5+"/>
<propertyname="ch.frankel.firstProp"/>
<propertyname="ch.frankel.secondProp"value="aValue"/>
<security>
<all-permissions/>
</security>
<jarhref="myMainJar.jar"/>
<jarhref="lib/myFirstDependency.jar"/>
<jarhref="lib/mySecondDependency.jar"/>
</resources>
<application-descmain-class="ch.frankel.blog.jws.MainClass">
<argument> myFirstParam </argument>
<argument> mySecondParam </argument>
</application-desc>
</jnlp>
步骤8:从旧版代码中删除错误
在Java Web Start的上下文中,某些旧版代码可能无法运行。 例如,忘记ClassLoader.getSystemResource()
:将其替换为以下代码段Thread.currentThread().getContextClassLoader().getResource()
,该代码段将在JWS和本地上下文中运行。 请记住,如果您遇到问题,很可能有人先于您:Google是您的朋友。
我希望本文能使您确信,只需很少的努力就可以使旧应用程序联机。 Java Web Start是实现此目的的标准化,经济高效且技术上合理的解决方案。
翻译自: https://blog.frankel.ch/web-start-your-legacy-applications/