《JavaTM程序设计语言 基础》第 2 部分
第 7 课:程序包和 JavaTM 档案文件格式

[<<后退] [目录] [下一课>>]

到此为止,您已通过导入包含您所需要类的程序包使用了来自 Java API 程序 库的类。包是组织相关类的一种比较方便的方法;在开发过程中,您也应把您的 应用程序文件组织到包中。包使之更容易查找和使用类文件并可帮助您在运行时 控制对类数据的访问。

当您的应用程序已经完全测试、调试并已备妥使用时,就可以按 JavaTM 档案(JAR)文件格式来使用该应用程序。JAR 文件格式是一种压缩文件打包格式 和工具,可用于把可执行文件与任何其它相关应用程序文件捆绑在一起,以便它 们能够作为一个整体使用。

本课将向您讲述如何把来自第2部分、第6课:国际化 的程序文件组织在包中,以及如何通过 JAR 文件格式使用可执行文件和其它相关 文件。正常情况下,应从开始开发阶段就使用包。


设置类程序包

类文件可以很容易地组织到包中。需要您执行的动作是把相关的类文件存放到 同一目录下、给该目录取一个与这些类的作用相关的名称,并在每个类文件的顶 部添加一行说明包名称(与其所在的目录同名)的信息。

例如,第2部分、第6课:国际化 中程序文件的类文 件和其它相关文件都可以分成三类文件:水果订单客户、查看订货客户和服务器 文件。尽管这三组类相互存在一定的关联,但它们有着单独的部署且用途各异。

生成目录

若要把国际化程序组织到三种程序包中,您就应该创建以下三个目录并把下列 源文件移动到对应的目录下:

  • client1
    • RMIEnglishApp.java
    • RMIFrenchApp.java
    • RMIGermanApp.java
    • MessagesBundle_de_DE.properties
    • MessagesBundle_en_US.properties
    • MessagesBundle_fr_FR.properties
    • index.html
    • rmiFapp.html
    • rmiGapp.html
    • rmiEapp.html
    • java.policy
  • client2
    • RMIClient2.java
    • MessagesBundle_de_DE.properties
    • MessagesBundle_en_US.properties
    • MessagesBundle_fr_FR.properties
    • java.policy
  • server
    • DataOrder.java
    • RemoteServer.java
    • Send.java
    • java.policy

声明程序包

每个 *.java 文件都需要在顶部进行包的声明,以反映出目录的 名称。而且,水果订单(client1)文件和查看订单 (client2) 客户类文件还需要服务器包的导入语句,这是因为它们 必须在运行时访问远程服务器对象。

以下是包含 RMIClient2.java 类文件的包声明和导入语句的一个示例:

//package declaration
package client2;

import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.*;
import javax.swing.*;

import java.io.*;
import java.net.*;

import java.rmi.*;
import java.rmi.server.*;

import java.util.*;
import java.text.*;

//Import server package
import server.*;

使类和域可被存取

若要把类文件组织在包中,您就必须把 server 目录中的服务器 类定义为 public,这样从 client1client2 目录中的类创建的客户程序才能实例化。若不把类指定为 public, 它就只能被同一包中的类所创建的对象实例化。

这样客户程序就可以访问水果订单数据,DataOrder 类的域也必 须为 publicRemoteServer 类和 Send 接口必须是 public 类,但它们的域并不一定是公有的,因为它们 没有公有数据。

没有 public 等类存取说明符的域和方法只能被同一包中的类 所创建的对象访问。

以下为新的 DataOrder 类。

package server;

import java.io.*;

//Make class public
public class DataOrder implements Serializable{

//Make fields public
  public String apples, peaches, pears, cardnum, custID;
  public double icost;
  public int itotal;
}

为找到属性文件而修改客户代码

在示例程序中,属性文件(Messages_*) 存放在有客户源文件的 目录中,便于随后对这些文件进行打包和调用。这样程序就可以包含属性文件, 而您则必须对客户源代码稍加改动。

创建 messages 变量的代码需要包含以下的目录(包名):

  messages = ResourceBundle.getBundle(
	"client2" + 
	File.separatorChar + 
	"MessagesBundle", currentLocale);

编译并运行示例程序

编译并运行组织到程序包中的示例程序与编译并运行前几课中的示例程序略有 不同。首先,您必须从程序包目录的某个上级目录执行编译器和解释器的命令; 其次,您必须把程序包目录指定给编译器和解释器命令。

编译

这些指令假设开发工作是在 zelda 主目录中完成的。

Unix:
cd /home/zelda/classes

javac server/Send.java
javac server/RemoteServer.java
javac client2/RMIClient2.java
javac client1/RMIFrenchApp.java
javac client1/RMIGermanApp.java
javac client1/RMIEnglishApp.java
rmic -d . server.RemoteServer
cp server/RemoteServer*.class 
	/home/zelda/public_html/classes
cp server/Send.class 
	/home/zelda/public_html/classes
cp server/DataOrder.class
        /home/zelda/public_html/classes
Win32:
cd \home\zelda\classes

javac server\Send.java
javac server\RemoteServer.java
javac client2\RMIClient2.java
javac client1\RMIFrenchApp.java
javac client1\RMIGermanApp.java
javac client1\RMIEnglishApp.java
rmic -d . server.RemoteServer
copy server\RemoteServer*.class
	\home\zelda\public_html\classes
copy server\Send.class 
	\home\zelda\public_html\classes
copy server\DataOrder.class
        \home\zelda\public_html\classes

注意: 命令行 rmic -d . server.RemoteServer 使用的 是 server.RemoteServer 而不是 server/RemoteServer, 所以 _stub_skel 类是采用程序包恰当地创 建的。

启动 rmi 注册程序:

Unix:
cd /home/zelda/public_html/classes
unsetenv CLASSPATH
rmiregistry &
Win32:
cd \home\zelda\public_html\classes
set CLASSPATH=
start rmiregistry 

启动服务器

Unix:

  cd /home/zelda/public_html/classes

  java -Djava.rmi.server.codebase=
	http://kq6py/~zelda/classes
  -Djava.rmi.server.hostname=kq6py.eng.sun.com
  -Djava.security.policy=
	server/java.policy server/RemoteServer
Win32:
  cd \home\zelda\public_html\classes

  java -Djava.rmi.server.codebase=
        file:c:\home\zelda\public_html\classes
  -Djava.rmi.server.hostname=kq6py.eng.sun.com
  -Djava.security.policy=
	server\java.policy server\RemoteServer

启动 RMIGermanApp 以下是调入德语版 applet 程序的 HTML 代码。请注意添加在 applet 类名前的 目录/包名前缀(client1/RMIGermanApp.class)。

 <HTML>
 <BODY>
 <APPLET CODE=client1/RMIGermanApp.class WIDTH=300 HEIGHT=300>
 </APPLET>
 </BODY>
 </HTML>
若要用 appletviewer 运行 applet 程序,则须从 client1 的上 级目录调用 HTML 文件,如下所述:
  cd /home/zelda/classes

  appletviewer rmiGapp.html

启动法语版的 RMIClient2

Unix:
  cd /home/zelda/classes

  java -Djava.rmi.server.codebase=
        http://kq6py/~zelda/classes
  -Djava.rmi.server.hostname=kq6py.eng.sun.com
  -Djava.security.policy=client2/java.policy
        client2/RMIClient2 kq6py.eng.sun.com fr FR
Win32:
  cd \home\zelda\classes

  java -Djava.rmi.server.codebase=
        file:c:\home\zelda\public_html\classes
  -Djava.rmi.server.hostname=kq6py.eng.sun.com
  -Djava.security.policy=client2\java.policy
        client2\RMIClient2 kq6py.eng.sun.com fr FR

通过 JAR 文件部署程序

测试和调试完毕后,部署两个客户和服务器文件的最佳方法是,把可执行文件 和其他相关文件捆绑到三个单独的 JAR 文件中,每个客户程序各一个 JAR 文件、 另一个 JAR 文件对应于服务器程序。

JAR 文件采用 ZIP 文件格式把文件压缩并捆绑到 JAR 文件中,或从 JAR 文件 中解压缩并拆包文件。JAR 文件使由多个文件组成的程序易于调用。浏览器可方 便地下载捆绑在 JAR 文件中的 applet 程序,这样下载 applet 程序及其相关文 件比下载没有经过捆绑的文件要快得多。

服务器文件组

以下是服务器文件:

  • RemoteServer.class
  • RemoteServer_skel.class
  • RemoteServer_stub.class
  • Send.class
  • DataOrder.class
  • java.policy

服务器文件的压缩和打包

若要把服务器文件压缩并打包到一个 JAR 文件中,则应在一个命令行上输入 以下命令。该命令在文件所在的目录下运行。如果要从其它目录下运行该命令, 就必须指明全路径名。

  jar cf server.jar 
	RemoteServer.class 
	RemoteServer_skel.class
	RemoteServer_stub.class
	Send.class
	DataOrder.class
	java.policy
jar 是指 jar 命令。如果键入的 jar 不带选项,屏幕上将出现以下的帮助屏。在帮助屏上,您会发现 jar 命令的 cf 选项表示创建一个名为 server.jar 的 新 JAR 文件,并将紧随其后的一系列文件放入新文件中。这个新的 JAR 文件将被 存放到当前目录下。
kq6py% jar
Usage: jar {ctxu}[vfm0M] [jar-file] [manifest-file] 
  [-C dir] files ...
Options:
  -c  create new archive
  -t  list table of contents for archive
  -x  extract named (or all) files from archive
  -u  update existing archive
  -v  generate verbose output on standard output
  -f  specify archive file name
  -m  include manifest information from specified 
        manifest file
  -0  store only; use no ZIP compression
  -M  Do not create a manifest file for the entries
  -C  change to the specified directory and 
        include the following file
If any file is a directory then it is processed 
  recursively.
The manifest file name and the archive file name 
  needs to be specified in the same order the 
  'm' and 'f' flags are specified.

Example 1: to archive two class files into an 
  archive called classes.jar: 
     jar cvf classes.jar Foo.class Bar.class 
Example 2: use an existing manifest file 'mymanifest' 
  and archive all the files in the foo/ directory 
  into 'classes.jar': 
     jar cvfm classes.jar mymanifest -C foo/ .
使用服务器文件时,您需要做的就是把 server.jar 文件移动到执 行这些文件的一个共享目录下。

服务器文件的解压缩和拆包

把 JAR 文件移动到最终位置后,就需要解压缩和拆包被压缩和打包的文件, 这样才能启动服务器。以下命令所完成的操作是从 server.jar 文 件(f)中提取(x)出所有的文件。

  jar xf server.jar

水果订单文件组

水果订单文件组(列举如下)由 applet 类、网页、译文文件和policy文件组 成。因为它们是在网络使用的,所以需要放置在可被网络服务器访问的目录下。 使用这些文件最简单的方法是把它们全部捆绑到一个 JAR 文件中并把它们复制到 各自的位置上。

  • RMIEnglishApp.class
  • RMIFrenchApp.class
  • RMIGermanApp.class
  • index.html (top-level web page where user chooses language)
  • rmiEapp.html (second-level web page for English)
  • rmiFapp.html (second-level web page for French)
  • rmiGapp.html (second-level web page for German)
  • MessagesBundle_de_DE.properties
  • MessagesBundle_en_US.properties
  • MessagesBundle_fr_FR.properties
  • java.policy

文件的压缩和打包

  jar cf applet.jar 
	RMIEnglishApp.class
	RMIFrenchApp.class
	RMIGermanApp.class
	index.html
	rmiEapp.html
	rmiFapp.html
	rmiGapp.html
	MessagesBundle_de_DE.properties
	MessagesBundle_en_US.properties
	MessagesBundle_fr_FR.properties
	java.policy
若要使用水果订单客户文件,则应把 applet.jar 文件复制到其最 终位置。

文件的解压缩和拆包

JAR 文件的 applet 程序可由未拆包的 HTML 文件调用。您要做 的全部事情就是为您网页中的 APPLET 标签指定 ARCHIVE 选项,这个选项把包含类文件的 JAR 文件名告诉给 appletviewer。在把 applet 类指定给 CODE 选项时,请务必包含程序包的目录。

您可以把译文(translation)文件和policy文件留在 JAR 文件中。在使用 appletviewer 时,从 JAR 文件调用的 applet 程序会在 JAR 文件中找到这些文 件。

<HTML>
<BODY>
<APPLET CODE=client1/RMIFrenchApp.class
  ARCHIVE="applet.jar"
  WIDTH=300
  HEIGHT=300>
</APPLET>
</BODY>
</HTML>

但是,为了能够把网页移动到它们的最终位置,您需要先对它们进行拆包。以 下就是完成这一操作的命令。所有代码都应写在一个命令行中。

  jar xv applet.jar index.html 	
	rmiEapp.html 
	rmiFapp.html 
	rmiGapp.html

注意: 若要从浏览器中运行 HTML 文件,就需要先拆包 JAR 文件,然后 把 java.policy 文件复制到您的主目录下并确保其名称正确 (Unix 下为.java.policy,Windows 下为 java.policy), 并安装 Java 插件。

查看订单文件组

查看订单的文件组(如下)由应用程序类文件和policy文件组成。

  • RMIClient2.class
  • java.policy

压缩和打包文件

  jar cf vieworder.jar RMIClient2.class java.policy
若要使用查看订单文件组,就要把 vieworder.jar 文件复制到其 最终位置。

文件的解压缩和拆包

  jar xf vieworder.jar

更多信息

有关程序包的更多信息,见 Java教程 中的 创建和使用程序包一课。

有关以上 JAR 文件和其他 JAR 文件格式的详细说明,见 Java教程 JAR 文件格式 一节。

[TOP]

 

 

常见问答
下载中心
产品简介
 
 
Solaris论坛
 
   
 
null