文档

Java™ 教程-Java Tutorials 中文版
下载型扩展
Trail: The Extension Mechanism
Lesson: Creating and Using Extensions

下载型扩展

下载型扩展是 JAR 文件中的类(和相关资源)的集合。JAR 文件的清单可以包含引用一个或多个下载型扩展的头。可以通过以下两种方式之一引用扩展:

请注意,清单中最多允许使用其中一个。由 Class-Path 头指示的下载型扩展名仅在下载它们的应用程序(例如 Web 浏览器)的生命周期内下载。它们的优点是客户端没有安装任何东西;它们的缺点是每次需要时都会下载它们。由 Extension-List 头下载的下载型扩展安装在下载它们的 JRE 的 /lib/ext 目录中。它们的优点是它们在第一次需要时下载;随后它们可以在不下载的情况下使用。但是,如本教程后面所示,部署它们会更复杂。

由于使用 Class-Path 头的下载型扩展更简单,因此我们先考虑它们。例如,假设 a.jarb.jar 是同一目录中的两个 JAR 文件,并且 a.jar 的清单包含这个 header:

Class-Path: b.jar

然后 b.jar 中的类用作 a.jar 中类的扩展类。a.jar 中的类可以调用 b.jar 中的类,而不必在类路径上指名 b.jar 的类。a.jar 本身可能是也可能不是扩展。如果 b.jara.jar 不在同一目录中,那么 Class-Path 头的值应设置为 b.jar 的相对路径名。

正在扮演下载型扩展的角色的类没有什么特别之处。它们被视为扩展,仅仅因为它们被其他 JAR 文件的清单引用。

为了更好地理解下载型扩展如何工作,让我们创建一个并将其用于使用。

一个例子

假设你要创建一个使用上一节的 RectangleArea 类的 applet:

public final class RectangleArea {  
    public static int area(java.awt.Rectangle r) {
        return r.width * r.height;
    }
}

在上一节中,你将 RectangleArea 类放入安装型扩展中,方法是将包含它的 JAR 文件放入 JRE 的 lib/ext 目录中。通过使它成为一个安装型扩展,你可以让任何应用程序使用 RectangleArea 类,就像它是 Java 平台的一部分一样。

如果你希望能够从 applet 使用 RectangleArea 类,情况会有所不同。例如,假设你有一个小程序 AreaApplet,它使用了类 RectangleArea

import java.applet.Applet;
import java.awt.*;

public class AreaApplet extends Applet {
    Rectangle r;

    public void init() {    
        int width = 10;
        int height = 5;

        r = new Rectangle(width, height);
    }

    public void paint(Graphics g) {
        g.drawString("The rectangle's area is " 
                      + RectangleArea.area(r), 10, 10);
    }
}

此 applet 实例化一个 10 x 5 矩形,然后使用 RectangleArea.area 方法显示矩形面积。

但是,你不能假设下载和使用你的 applet 的每个人都将在其系统上提供 RectangleArea 类,作为安装型扩展或其他方式。解决该问题的一种方法是从服务器端提供 RectangleArea 类,并且可以通过将其用作下载型扩展来实现。

为了了解它是如何完成的,我们假设你已将 AreaApplet 打包在名为 AreaApplet.jar 的 JAR 文件中,并且打包了 RectangleArea 类在 RectangleArea.jar 中。为了将 RectangleArea.jar 视为下载型扩展,RectangleArea.jar 必须在 AreaApplet.jar 的清单中列出 Class-Path 头。AreaApplet.jar 的清单可能如下所示,例如:

Manifest-Version: 1.0
Class-Path: RectangleArea.jar

此清单中 Class-Path 头的值为 RectangleArea.jar,未指定路径,表示 RectangleArea.jar 位于与 applet 的 JAR 文件相同的目录。

有关 Class-Path 头的更多信息

如果 applet 或应用程序使用多个扩展,你可以在清单中列出多个 URL。例如,以下是有效的头:

Class-Path: area.jar servlet.jar images/

Class-Path 头中,列出的所有未以“/”结尾的 URL 都是 JAR 文件。以“/”结尾的 URL 表示目录。在前面的示例中,images/ 可能是包含 applet 或应用程序所需资源的目录。

请注意,清单文件中只允许一个 Class-Path 头,并且清单中的每一行长度不得超过 72 个字符。如果需要指定多于适合一行的类路径条目,可以将它们扩展到后续的延续行。以两个空格开始每个延续行。例如:

Class-Path: area.jar servlet.jar monitor.jar datasource.jar
  provider.jar gui.jar

未来版本可以消除每个头仅具有一个实例的限制,以及行仅限于 72 个字符的限制。

下载型扩展可以是“菊花链的”,这意味着一个下载型扩展的清单可以有一个 Class-Path 头,其引用第二个扩展,其引用第三个扩展,依此类推。

安装下载型扩展

在上面的示例中,applet 下载型扩展只有在加载 applet 的浏览器仍在运行时才可用。但是,如果 applet 和扩展程序的清单中包含其他信息,则 applet 可以触发扩展程序的安装。

由于此机制扩展了平台的核心 API,因此应明智地应用它。它很少适用于单个或一小组应用程序使用的接口。所有可见符号应遵循反向域名和类层次结构规范。

基本要求是 applet 和它使用的扩展都在其清单中提供版本信息,并且它们是签名的。版本信息允许 Java Plug-in 确保扩展代码具有 applet 期望的版本。例如,AreaApplet 可以在其清单中指定 areatest 扩展:

Manifest-Version: 1.0
Extension-List: areatest
areatest-Extension-Name: area
areatest-Specification-Version: 1.1
areatest-Implementation-Version: 1.1.2
areatest-Implementation-Vendor-Id: com.example
areatest-Implementation-URL: http://www.example.com/test/area.jar

area.jar 中的清单将提供相应的信息:

Manifest-Version: 1.0
Extension-Name: area
Specification-Vendor: Example Tech, Inc
Specification-Version: 1.1
Implementation-Vendor-Id: com.example
Implementation-Vendor: Example Tech, Inc
Implementation-Version: 1.1.2

applet 和扩展都必须由同一个签名者签名。签名 jar 文件将就地修改它们,在其清单文件中提供更多信息。签名有助于确保只安装受信任的代码。签名 jar 文件的一种简单方法是首先创建一个密钥库,然后使用它来保存 applet 和扩展的证书。例如:

keytool -genkey -dname "cn=Fred" -alias test  -validity 180

系统将提示你输入密钥库和密钥密码。生成密钥后,可以对 jar 文件进行签名:

jarsigner AreaApplet.jar test
jarsigner area.jar test

系统将提示你输入密钥库和密钥密码。有关 keytooljarsigner 和其他安全工具的更多信息,请参阅 Summary of Tools for the Java 2 Platform Security

这是 AreaDemo.html,它加载 applet 并导致下载和安装扩展代码:

<html>
<body>
  <applet code="AreaApplet.class" archive="AreaApplet.jar"/>
</body>
</html>

首次加载页面时,会告知用户 applet 需要安装扩展程序。随后的对话框会通知用户签名的 applet。接受两者会在 JRE 的 lib/ext 文件夹中安装扩展并运行 applet。

重新启动 Web 浏览器并加载相同的 Web 页面后,仅显示有关 applet 签名者的对话框,因为已经安装了 area.jar。如果在不同的 Web 浏览器中打开 AreaDemo.html(假设两个浏览器使用相同的 JRE),也是如此。


Previous page: Installed Extensions
Next page: Understanding Extension Class Loading