A Guide to the Java Web Start – Java Web Start指南

最后修改: 2017年 3月 29日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

This article explains what Java Web Start (JWS) is, how to configure it on the server side, and how to create a simple application.

本文解释了什么是Java Web Start(JWS),如何在服务器端配置它,以及如何创建一个简单的应用程序。

Note: The JWS has been removed from the Oracle JDK starting with Java 11. As an alternative, consider using OpenWebStart.

注意:从 Java 11 开始,JWS 已从 Oracle JDK 中删除。作为替代方案,请考虑使用OpenWebStart

2. Introduction

2.简介</strong

JWS is a runtime environment that comes with the Java SE for the client’s web browser and has been around since Java version 5.

JWS是客户端网络浏览器的Java SE自带的运行环境,从Java第五版开始就存在了。

With the download of the JNLP files (also known as Java Network Launch Protocol) from the web server, this environment allows us to run JAR packages referenced by it remotely.

随着从网络服务器下载JNLP文件(也被称为Java网络启动协议),这个环境允许我们远程运行它所引用的JAR包。

Simply put, the mechanism loads and runs Java classes on a client’s computer with a regular JRE installation. It allows some extra instructions from Jakarta EE as well. However, security restrictions are strictly applied by the client’s JRE, usually warning the user for untrustworthy domains, lack of HTTPS and even unsigned JARs.

简单地说,该机制在客户的计算机上加载和运行Java类,并安装了常规的JRE。它也允许来自Jakarta EE的一些额外指令。然而,安全限制是由客户端的JRE严格执行的,通常会警告用户不值得信任的域,缺乏HTTPS,甚至是没有签名的JAR。

From a generic website, one can download a JNLP file to execute a JWS application. Once downloaded, it can be run directly from a desktop shortcut or the Java Cache Viewer. After that, it downloads and executes JAR files.

从一个通用的网站,人们可以下载一个JNLP文件来执行一个JWS应用程序。下载后,可以直接从桌面快捷方式或Java Cache Viewer中运行。之后,它下载并执行JAR文件。

This mechanism can be very helpful to deliver a graphical interface that is not web-based (HTML free), such as a secure file transfer application, a scientific calculator, a secure keyboard, a local image browser and so on.

这种机制对于提供不基于网络(无HTML)的图形界面非常有帮助,如安全文件传输应用程序、科学计算器、安全键盘、本地图像浏览器等。

3. A Simple JNLP Application

3.一个简单的JNLP应用

A good approach is to write an application and package it into a WAR file for regular web servers. All we need is to write our desired application (usually with Swing) and package it into a JAR file. This JAR must then, in turn, be packaged into a WAR file together with a JNLP that will reference, download and execute its application’s Main class normally.

一个好的方法是编写一个应用程序,并将其打包成一个WAR文件,用于普通的Web服务器。我们所需要的是编写我们所需要的应用程序(通常是用Swing)并将其打包成一个JAR文件。然后,这个JAR必须和一个JNLP一起打包成WAR文件,这个JNLP将正常引用、下载和执行其应用程序的Main类。

There is no difference with a regular web application packaged in a WAR file, except for the fact that we need a JNLP file to enable the JWS, as will be demonstrated below.

除了我们需要一个JNLP文件来启用JWS外,与普通的WAR文件打包的Web应用程序没有任何区别,下面将进行演示。

3.1. Java Application

3.1.Java应用程序

Let’s start by writing a simple Java application:

让我们从编写一个简单的Java应用程序开始。

public class Hello {
    public static void main(String[] args) {
        JFrame f = new JFrame("main");
        f.setSize(200, 100);
        f.setLocationRelativeTo(null);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JLabel label = new JLabel("Hello World");
        f.add(label);
        f.setVisible(true);
    }
}

We can see that this is a pretty straightforward Swing class. Indeed, nothing was added to make it JWS compliant.

我们可以看到,这是一个相当直接的Swing类。事实上,没有添加任何东西来使其符合JWS标准。

3.2. Web Application

3.2.网络应用

All we need is to JAR package this example Swing class into a WAR file along with the following JNLP file:

我们所需要的是将这个Swing范例的JAR包和下面的JNLP文件一起打包成一个WAR文件。

<?xml version="1.0" encoding="UTF-8"?>
<jnlp spec="1.0+" 
  codebase="http://localhost:8080/jnlp-example">
    <information>
        <title>Hello</title>
        <vendor>Example</vendor>
    </information>
    <resources>
        <j2se version="1.2+"/>
        <jar href="hello.jar" main="true" />
    </resources>
    <application-desc/>
</jnlp>

Let’s name it hello.jndl and place it under any web folder of our WAR. Both the JAR and WAR are downloadable, so we don’t need to worry putting the JAR in a lib folder.

让我们把它命名为hello.jndl,并把它放在WAR的任何Web文件夹下。JAR和WAR都是可以下载的,所以我们不需要担心把JAR放在lib文件夹中。

The URL address to our final JAR is hard coded in the JNLP file, which can cause some distribution problems. If we change deployment servers, the application won’t work anymore.

我们最终的JAR的URL地址是在JNLP文件中硬编码的,这可能导致一些分发问题。如果我们改变部署服务器,应用程序就不能再工作了。

Let’s fix that with a proper servlet later in this article. For now, let’s just place the JAR file for download in the root folder as the index.html, and link it to an anchor element:

让我们在本文后面用一个适当的servlet来解决这个问题。现在,让我们把供下载的JAR文件作为index.html放在根文件夹中,并把它链接到一个锚元素上。

<a href="hello.jnlp">Launch</a>

Let’s also set the main class in our JAR Manifest. This can be achieved by configuring the JAR plugin in the pom.xml file. Similarly, we move the JAR file outside of the WEB-INF/lib, since it is meant for download only, i.e. not for the classloader:

让我们也在我们的JAR Manifest中设置主类。这可以通过在pom.xml文件中配置JAR插件来实现。同样,我们把JAR文件移到WEB-INF/lib之外,因为它只用于下载,也就是说,不用于classloader。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    ...
    <executions>
        <execution>
            <phase>compile</phase>
            <goals>
                <goal>jar</goal>
            </goals>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>
                            com.example.Hello
                        </mainClass>
                    </manifest>
                </archive>
                <outputDirectory>
                    ${project.basedir}/target/jws
                </outputDirectory>
            </configuration>
        </execution>
    </executions>
</plugin>

4. Special Configurations

4.特殊配置

4.1. Security Issues

4.1.安全问题

To run an application, we need to sign the JAR. Creating a valid certificate and using the JAR Sign Maven Plugin goes beyond the scope of this article, but we can bypass this security policy for development purposes, or if we have administrative access to our user’s computer.

要运行一个应用程序,我们需要签署JAR。创建一个有效的证书并使用JAR Sign Maven插件超出了本文的范围,但我们可以出于开发目的绕过这一安全策略,或者如果我们对用户的电脑有管理权限的话。

To do so, we need to add the local URL (for instance: http://localhost:8080) to the security exceptions list of the JRE installation on the computer where the application will be executed. It can be found by opening the Java Control Panel (on Windows, we can found it via the Control Panel) on the Security tab.

要做到这一点,我们需要将本地URL(例如:http://localhost:8080)添加到将执行该应用程序的计算机上的JRE安装的安全例外列表中。可以通过打开Java控制面板(在Windows中,我们可以通过控制面板找到它)的安全标签找到它。

5. The JnlpDownloadServlet

5.JnlpDownloadServlet

5.1. Compression Algorithms

5.1.压缩算法

There is a special servlet that can be included in our WAR. It optimizes the download by looking for the most compressed compiled version of our JAR file if available, and also fix the hard coded codebase value on the JLNP file.

有一个特殊的Servlet,可以包含在我们的WAR中。它通过寻找我们的JAR文件的最压缩的编译版本(如果有的话)来优化下载,同时也修复JLNP文件上的硬编码codebase值。

Since our JAR will be available for download, it’s advisable to package it with a compression algorithm, such as Pack200, and deliver the regular JAR and any JAR.PACK.GZ or JAR.GZ compressed version at the same folder so that this servlet can choose the best option for each case.

由于我们的JAR将可供下载,建议用压缩算法打包,如Pack200,并在同一文件夹下交付普通JAR和任何JAR.PACK.GZ或JAR.GZ压缩版本,以便该Servlet能够为每种情况选择最佳方案。

Unfortunately, there is no stable version of a Maven plugin yet for this compression algorithm, but we may work with the Pack200 executable that comes with the JRE (usually, installed on the path {JAVA_SDK_HOME}/jre/bin/).

不幸的是,目前还没有针对这种压缩算法的稳定版本的Maven插件,但我们可以使用JRE附带的Pack200可执行文件(通常安装在{JAVA_SDK_HOME}/jre/bin/路径上)。

Without changing our JNLP and by placing the jar.gz and jar.pack.gz versions of the JAR in the same folder, the servlet picks the better one once it gets a call from a remote JNLP. This enhances the user experience and optimizes network traffic.

在不改变我们的JNLP的情况下,通过将JAR的jar.gzjar.pack.gz版本放在同一个文件夹中,一旦收到来自远程JNLP的调用,servlet就会挑选更好的版本。这增强了用户体验并优化了网络流量。

5.2. Codebase Dynamic Substitution

5.2.代码库动态替换

The servlet can also perform dynamic substitutions for hardcoded URLs in the <jnlp spec=”1.0+” codebase=”http://localhost:8080/jnlp-example”> tag. By changing the JNLP to the wildcard <jnlp spec=”1.0+” codebase=”$$context”>, it delivers the same final rendered tag.

该Servlet还可以对<jnlp spec=”1.0+” codebase=”http://localhost:8080/jnlp-example”>标签中的硬编码URL进行动态替换。通过将JNLP改为通配符<jnlp spec=”1.0+” codebase=”$context”>,它可以提供相同的最终渲染标签。

The servlet also works with the wildcards $$codebase, $$hostname, $$name and $$site, which will resolve “http://localhost:8080/jnlp-example/“, “localhost:8080“, “hello.jnlp“, and “http://localhost:8080” respectively.

该Servlet还可以使用通配符$codebase$hostname$name$site,它们将分别解决”http://localhost:8080/jnlp-example/“、”localhost:8080“、”hello.jnlp“和”http://localhost:8080“。

5.3. Adding the Servlet to the Classpath

5.3.将Servlet添加到Classpath中

To add the servlet, let’s configure a normal servlet mapping for JAR and JNLP patterns to our web.xml:

为了添加Servlet,让我们为JAR和JNLP模式配置一个正常的Servlet映射到我们的web.xml

<servlet>
    <servlet-name>JnlpDownloadServlet</servlet-name>
    <servlet-class>
        jnlp.sample.servlet.JnlpDownloadServlet
    </servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>JnlpDownloadServlet</servlet-name>
    <url-pattern>*.jar</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>JnlpDownloadServlet</servlet-name>
    <url-pattern>*.jnlp</url-pattern>
</servlet-mapping>

The servlet itself comes in a set of JARs (jardiff.jar and jnlp-servlet.jar) that are nowadays located on the Demos & Samples section on the Java SDK download page.

Servlet本身包含在一组JAR中(jardiff.jarjnlp-servlet.jar),如今位于Java SDK下载页面的Demo & Samples部分。

In the GitHub example, these files are included in the java-core-samples-lib folder and are included as web resources by the Maven WAR plugin:

在GitHub的例子中,这些文件包含在java-core-samples-lib文件夹中,并被Maven WAR插件作为网络资源包含。

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    ...
    <configuration>
        <webResources>
            <resource>
                <directory>
                    ${project.basedir}/java-core-samples-lib/
                </directory>
                <includes>
                    <include>**/*.jar</include>
                </includes>
                <targetPath>WEB-INF/lib</targetPath>
            </resource>
        </webResources>
    </configuration>
</plugin>

6. Final Thoughts

6.最后的想法

Java Web Start is a tool that may be used in (intranet) environments where there is no application server. Also, for applications that need to manipulate local user files.

Java Web Start是一种工具,可用于没有应用服务器的(内联网)环境。另外,对于需要操作本地用户文件的应用程序。

An application is shipped to the end user by a simple download protocol, without any additional dependencies or configuration, except for some security concerns (HTTPS, signed JAR, etc.).

一个应用程序通过一个简单的下载协议运送给最终用户,除了一些安全问题(HTTPS,签名的JAR等),没有任何额外的依赖或配置。

In the Git Example, the full source code described in this article is available for download. We can download it directly from GitHub to an OS with Tomcat and Apache Maven. After download, we need to run the mvn install command from the source directory and copy the generated jws.war file from the target to the webapps folder of the Tomcat installation.

Git实例中,本文所述的完整源代码可供下载。我们可以直接从GitHub下载到装有Tomcat和Apache Maven的操作系统中。下载后,我们需要从源目录运行mvn install命令,并将生成的jws.war文件从target复制到Tomcat安装的webapps文件夹。

After that, we can start Tomcat as usual.

之后,我们可以像往常一样启动Tomcat。

From a default Apache Tomcat installation, the example will be available at the URL http://localhost:8080/jws/index.html.

在默认的Apache Tomcat安装中,该例子将在URL http://localhost:8080/jws/index.html上提供。