用RMI开发基于Java的企业分布式应用(2)
作者:佚名; 更新时间:2014-12-05
lic interface InfoDistributeRemote extends Remote{
public String getRemoteInfo() throws RemoteException;
}
5.2 实现远程接口
这是一个实现远程对象的类。如果实现了远程接口,就能够覆盖(override)该对象中的所有方法,因此,远程对象的实现类将真正包含我们希望导出的方法的代码。
在远程信息发布系统中,我们至少实现一个远程接口的对象,它就是远程可访问的对象。这里,InfoDistributeService类可以为我们生成远程可访问对象的实例:
// -----------InfoDistributeService.java------------------
package enterprise. distribute;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class InfoDistributeService
extends UnicastRemoteObject implements InfoDistributeRemote{
public InfoDistributeService() throws RemoteException{
super();
}
// The return value of the method only for testing...
public String getRemoteInfo(){
return “Hello! I am a remote object.”;
}
}
InfoDistributeService类实现远程接口InfoDistributeRemote,并继承java.rmi.server.UnicastRemoteObject。由于符合InfoDistributeRemote接口,因此该类除构造方法之外,还应有getRemoteInfo()方法,而且必须将该方法实现。
同时我们注意到,getRemoteInfo()方法抛出了java.rmi.RemoteException异常。由于远程方法调用过程中,要进行很多的低级网络操作,因此网络错误可能在调用过程中随时发生,这样,远程接口中的每个方法(尽管这里只有一个getRemoteInfo()方法)都必须抛出RemoteException异常,而且,java.rmi.RemoteException都要在代码中显式处理,即将所有RMI活动涉及的代码都要放在try-catch块中。
5.3 准备供远程调用的服务器对象
这是一个作为服务器使用的类,它是相对于要访问远程方法的客户端而言的。它存储着绑定的字符串和对象。
将远程对象设置成接受远程调用就像启动了侦听ServerSocket对象的socket服务器。事实上在使用RMI时,TCP/IP协议的传输方式,在幕后发生了很多底层网络操作,但是此刻,用户不需要知道这些细节,只需要逐步导出远程对象:
在Java开发工具的较新版本JDK 1.4中,可以选择java.rmi.UnicastRemoteObject或者java.rmi.Activation.Activatable。其中,更多用到的是UnicastRemoteObject,因为它顾名思义,就是在客户机与服务器对象实例之间建立一对一连接。
5.4 生成Stub和Skeleton
由RMI生成的调动与反调动的远程调动代码也和Java的其它代码一样,都包含在后缀是.class的文件中。
运用RMI之后,在客户机上生成的调动参数和反调动返回值的代码称为残根(Stub),服务器上生成的反调动参数和进行实际方法调用调动返回值的代码称为框架(Skeleton)。
可以使用RMI自带的命令行工具rmic(即RMI Compiler),先扫描远程对象的.class文件,随之生成残根与框架代码。工具rmic的原理如图1。
5.5 远程客户端:这是一个帮助我们访问远程方法提供帮助的类,它也是最终用户。我们将使用查找和调用远程方法的方法在该类中调用远程方法。
典型的rmic调用如下(在当前目录):
我们有了远程接口和实现,就可以用rmic对类进行编译,生成Stub和Skeleton,在命令行窗口中使用以下代码行:
// compile all java source files
javac enterprise\distribute\*.java
// make stub and skeleton code
rmic enterprise.distribute.InfoDistributeService
运行完毕后,在当前目录生成下列文件(即调动代码):
InfoDistributeService_Stub.class
InfoDistributeService_Skel.class
5.5 用rmiregistry找到远程对象
导出服务器方的对象之后,就可以远程访问,但客户机还要设法与这些远程对象取得联系。
由于分布式应用程序可能涉及许多不同机器,因此通信的所有机器对之间需要建立初始连接,换句话说,就是要设法找到初始远程对象,这项工作通过rmiregistry命令执行。
JDK开发工具提供了实用程序RMI Registry,用来维护文本名和远程对象之间的映射,可以进行远程访问。
5.5.1 在客户机方,RMI注册表可以通过同一java.rmi.Naming类的lookup()静态方法用程序访问。例如,远程主机为iServer,远程对象实例为InfoDistributeService实例,远程端口号为5678,则客户机如果查找远程主机iServer中的远程InfoDistributeService实例,那么引用实例时须使用远程接口InfoDistributeRemote,信捷职称论文写作发表网,代码如下:
InfoDistributeRemote iServer=( InfoDistributeRemote)
Naming.lookup(“rmi://iServer:5678/InfoDistributeService”);
5.5.2 在服务器方,导出的远程对象可以通过java.rmi.Naming类在本地注册rmiregistry的运行实例。例如,用rebind()方法将iService中的InfoDistributeService的实例与名称InfoDistributeService相关联。
InfoDistributeService iService=new InfoDistributeService();
Naming.rebind(“/ InfoDistributeService”,iService);
综上所述,InfoDistributeRemote是个Java接口,因此iServer实际上是实现InfoDistributeRemote接口的本地对象实例,它不在远程,而是远程InfoDistributeService的本地表示。也就是说,它是由前述rmic工具自动生成的残根码InfoDistributeService_Stub.class的本地实例。图3显示了远程对象调用的工作原理。
图2 远程对象调用的工作原理
从图2可以看出,客户机实现通过iServer变量维护远程对象的调用。事实上,iServer引用变量是实现InfoDistribute接口的对象的本地引用,该对象是InfoDistributeService残根实现。这个残根和服务器方的框架一起通过InfoDistributeRemote接口调动/反调动所有远程调用。
当我们把InfoDistributeService看成是实现InfoDistributeRemote接口的本地实例的时候,残根代码只在幕后进行工作,而实现这一切则变得非常透明。
由上述原理,可以进一步设计完善客户机和服务器代码,进而编写出完整的应用程序。
5.6 运行测试RMI分布式应用
在确认已经设计好必须的几大类模块后,我们开始按以下步骤,运行并测试该信息发布系统的基本功能(即仅仅实现远程接口中声明的getRemoteInfo()方法)。
5.6.1 在前面定义的包enterprise.distribute中,执行javac命令编译后缀为.java的源文件。
javac enterprise/distribute/*.java
5.6.2 接着,用RMIC工具生成残根与框架。
rmic enterprise.distribute.InfoDistributeService
5.6.3 编译之后,需要确定客户机与服务器发行版本的内容。因此,需用jar命令,将客户机与服务器发行版本包装成 .jar文件。 其中,包装服务器的文件命令如下:
jar cvf InfoDistributeService.jar
enterprise\distribute\InfoDistributeService.class
enterprise\distribute\InfoDistributeRemote.class
enterprise\distribute\InfoDistributeService_Stub.class
enterprise\distribute\InfoDistributeService_Skel.class
同样,包装客户机的类似于以上命令。
5.6.4 运行RMI应用程序
完成了第一阶段的所有RMI试验,然后运行信息发布应用程序。按照Java规范,需要依次启动下列项目:
5.6.4.1 启动RMIRegistry
在代码目录中用以下命令启动rmiregistry实例,使之在控制台开始运行。
start rmiregistry
5.6.4.2 启动服务器
直接启动服务器,生成InfoDistributeService远程对象的实例,并向注册表注册。
start java –classpath InfoDistributeService.jar
enterprise.distribute.InfoDistributeService
5.6.4.3 启动客户机
最后,用java –classpath RemoteClient.jar 命令启动客户机,然后通过rmiregistry找到远程信息发布服务,再通过远程调用得到所
public String getRemoteInfo() throws RemoteException;
}
5.2 实现远程接口
这是一个实现远程对象的类。如果实现了远程接口,就能够覆盖(override)该对象中的所有方法,因此,远程对象的实现类将真正包含我们希望导出的方法的代码。
在远程信息发布系统中,我们至少实现一个远程接口的对象,它就是远程可访问的对象。这里,InfoDistributeService类可以为我们生成远程可访问对象的实例:
// -----------InfoDistributeService.java------------------
package enterprise. distribute;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class InfoDistributeService
extends UnicastRemoteObject implements InfoDistributeRemote{
public InfoDistributeService() throws RemoteException{
super();
}
// The return value of the method only for testing...
public String getRemoteInfo(){
return “Hello! I am a remote object.”;
}
}
InfoDistributeService类实现远程接口InfoDistributeRemote,并继承java.rmi.server.UnicastRemoteObject。由于符合InfoDistributeRemote接口,因此该类除构造方法之外,还应有getRemoteInfo()方法,而且必须将该方法实现。
同时我们注意到,getRemoteInfo()方法抛出了java.rmi.RemoteException异常。由于远程方法调用过程中,要进行很多的低级网络操作,因此网络错误可能在调用过程中随时发生,这样,远程接口中的每个方法(尽管这里只有一个getRemoteInfo()方法)都必须抛出RemoteException异常,而且,java.rmi.RemoteException都要在代码中显式处理,即将所有RMI活动涉及的代码都要放在try-catch块中。
5.3 准备供远程调用的服务器对象
这是一个作为服务器使用的类,它是相对于要访问远程方法的客户端而言的。它存储着绑定的字符串和对象。
将远程对象设置成接受远程调用就像启动了侦听ServerSocket对象的socket服务器。事实上在使用RMI时,TCP/IP协议的传输方式,在幕后发生了很多底层网络操作,但是此刻,用户不需要知道这些细节,只需要逐步导出远程对象:
在Java开发工具的较新版本JDK 1.4中,可以选择java.rmi.UnicastRemoteObject或者java.rmi.Activation.Activatable。其中,更多用到的是UnicastRemoteObject,因为它顾名思义,就是在客户机与服务器对象实例之间建立一对一连接。
5.4 生成Stub和Skeleton
由RMI生成的调动与反调动的远程调动代码也和Java的其它代码一样,都包含在后缀是.class的文件中。
运用RMI之后,在客户机上生成的调动参数和反调动返回值的代码称为残根(Stub),服务器上生成的反调动参数和进行实际方法调用调动返回值的代码称为框架(Skeleton)。
可以使用RMI自带的命令行工具rmic(即RMI Compiler),先扫描远程对象的.class文件,随之生成残根与框架代码。工具rmic的原理如图1。
5.5 远程客户端:这是一个帮助我们访问远程方法提供帮助的类,它也是最终用户。我们将使用查找和调用远程方法的方法在该类中调用远程方法。
典型的rmic调用如下(在当前目录):
我们有了远程接口和实现,就可以用rmic对类进行编译,生成Stub和Skeleton,在命令行窗口中使用以下代码行:
// compile all java source files
javac enterprise\distribute\*.java
// make stub and skeleton code
rmic enterprise.distribute.InfoDistributeService
运行完毕后,在当前目录生成下列文件(即调动代码):
InfoDistributeService_Stub.class
InfoDistributeService_Skel.class
5.5 用rmiregistry找到远程对象
导出服务器方的对象之后,就可以远程访问,但客户机还要设法与这些远程对象取得联系。
由于分布式应用程序可能涉及许多不同机器,因此通信的所有机器对之间需要建立初始连接,换句话说,就是要设法找到初始远程对象,这项工作通过rmiregistry命令执行。
JDK开发工具提供了实用程序RMI Registry,用来维护文本名和远程对象之间的映射,可以进行远程访问。
5.5.1 在客户机方,RMI注册表可以通过同一java.rmi.Naming类的lookup()静态方法用程序访问。例如,远程主机为iServer,远程对象实例为InfoDistributeService实例,远程端口号为5678,则客户机如果查找远程主机iServer中的远程InfoDistributeService实例,那么引用实例时须使用远程接口InfoDistributeRemote,信捷职称论文写作发表网,代码如下:
InfoDistributeRemote iServer=( InfoDistributeRemote)
Naming.lookup(“rmi://iServer:5678/InfoDistributeService”);
5.5.2 在服务器方,导出的远程对象可以通过java.rmi.Naming类在本地注册rmiregistry的运行实例。例如,用rebind()方法将iService中的InfoDistributeService的实例与名称InfoDistributeService相关联。
InfoDistributeService iService=new InfoDistributeService();
Naming.rebind(“/ InfoDistributeService”,iService);
综上所述,InfoDistributeRemote是个Java接口,因此iServer实际上是实现InfoDistributeRemote接口的本地对象实例,它不在远程,而是远程InfoDistributeService的本地表示。也就是说,它是由前述rmic工具自动生成的残根码InfoDistributeService_Stub.class的本地实例。图3显示了远程对象调用的工作原理。
图2 远程对象调用的工作原理
从图2可以看出,客户机实现通过iServer变量维护远程对象的调用。事实上,iServer引用变量是实现InfoDistribute接口的对象的本地引用,该对象是InfoDistributeService残根实现。这个残根和服务器方的框架一起通过InfoDistributeRemote接口调动/反调动所有远程调用。
当我们把InfoDistributeService看成是实现InfoDistributeRemote接口的本地实例的时候,残根代码只在幕后进行工作,而实现这一切则变得非常透明。
由上述原理,可以进一步设计完善客户机和服务器代码,进而编写出完整的应用程序。
5.6 运行测试RMI分布式应用
在确认已经设计好必须的几大类模块后,我们开始按以下步骤,运行并测试该信息发布系统的基本功能(即仅仅实现远程接口中声明的getRemoteInfo()方法)。
5.6.1 在前面定义的包enterprise.distribute中,执行javac命令编译后缀为.java的源文件。
javac enterprise/distribute/*.java
5.6.2 接着,用RMIC工具生成残根与框架。
rmic enterprise.distribute.InfoDistributeService
5.6.3 编译之后,需要确定客户机与服务器发行版本的内容。因此,需用jar命令,将客户机与服务器发行版本包装成 .jar文件。 其中,包装服务器的文件命令如下:
jar cvf InfoDistributeService.jar
enterprise\distribute\InfoDistributeService.class
enterprise\distribute\InfoDistributeRemote.class
enterprise\distribute\InfoDistributeService_Stub.class
enterprise\distribute\InfoDistributeService_Skel.class
同样,包装客户机的类似于以上命令。
5.6.4 运行RMI应用程序
完成了第一阶段的所有RMI试验,然后运行信息发布应用程序。按照Java规范,需要依次启动下列项目:
5.6.4.1 启动RMIRegistry
在代码目录中用以下命令启动rmiregistry实例,使之在控制台开始运行。
start rmiregistry
5.6.4.2 启动服务器
直接启动服务器,生成InfoDistributeService远程对象的实例,并向注册表注册。
start java –classpath InfoDistributeService.jar
enterprise.distribute.InfoDistributeService
5.6.4.3 启动客户机
最后,用java –classpath RemoteClient.jar 命令启动客户机,然后通过rmiregistry找到远程信息发布服务,再通过远程调用得到所
热门论文