论文导读:Java作为一种风靡一时的网络开发语言,其巨大的威力就体现在它强大的开发分布式网络应用的能力上,而RMI就是开发百分之百纯Java的网络分布式应用系统的核心解决方案之一。
关键词:RMI,JAVA,分布式远程方法调用
Java RMI(RomoteMethod Invocation 远程方法调用)是用Java在JDK1.1中实现的,它大大增强了Java开发分布式应用的能力。其实它可以被看作是RPC的Java版本。但是传统RPC并不能很好地应用于分布式对象系统。而Java RMI则支持存储于不同地址空间的程序级对象之间彼此进行通信,实现远程对象之间的无缝远程调用。RMI目前使用Java远程消息交换协议JRMP(Java Remote Messaging Rrotocol)进行通信。JRMP是专为Java的远程对象制定的协议。因此,Java RMI具有Java的”Write Once,Run Anywhere”的优点,是分布式应用系统的百分之百纯Java解决方案。用Java RMI开发的应用系统可以部署在任何支持JRE的平台上。发表论文。但由于JRMP是专为Java对象制定的,因此,RMI对用用非Java语言开发的应用系统的支持不足。不能与用非Java语言书写的对象进行通信。
RMI系统原理
RMI应用程序通常包括两个独立的程序:服务器程序和客户机程序。典型的服务器应用程序将创建多个远程对象,使这些远程对象能够被引用,然后等待客户机调用这些远程对象的方法。而典型的客户机程序则从服务器中得到一个或多个远程对象的引用,然后调用远程对象的方法。RMI为服务器和客户机进行通信和信息传递提供了一种机制。
在与远程对象的通信过程中,RMI使用标准机制:Stub和Skeleton。远程对象的Stub担当远程对象的客户本地代表或代理人角色。发表论文。调用程序将调用本地Stub的方法,而本地Stub将负责执行对远程对象的方法调用。在RMI中,远程对象的Stub与该远程对象所实现的远程接口集相同。调用Stub的方法时将执行下列操作:(1)初始化与包含远程对象的远程虚拟机的连接;(2)对远程虚拟机的参数进行序列化(写入并传输);(3)等待方法调用结果;(4)反序列化(读取)返回值或返回的异常;(5)将值返回给调用程序。为了向调用程序展示比较简单的调用机制,Stub将参数的序列化和网络级通信等细节隐藏了起来。在远程虚拟机中,每个远程对象都可以都可以有相应的Skeleton。Skeleton负责将调用分配给实际的远程对象实现。它在接收方法调用时执行下列操作:(1)反序列化(读取)远程方法的参数;(2)调用实际远程对象实现上的方法;(3)将结果(返回值或异常)序列化(写入并传输)给调用程序。Stub和Skeleton由rmic编译器生成。
在RMI分布式应用系统中,服务器与客户机之间传递的Java对象必须是可序列化的对象。不可序列化的对象不能在对象流中进行传递。对象序列化扩展了核心Java输入、输出类,同时也支持对象。对象序列化支持把对象编码以及通过它们可访问到的对象编码变成字节流;同时它也支持流中对象图形的互补重构造。序列化用于轻型持久性和借助于套接字或远程方法调用进行的通信。
利用RMI编写分布式对象应用程序需要完成以下工作:(1)定位远程对象。发表论文。应用程序可使用RMI的简单命名工具rmiregistry来注册它的远程对象。(2)与远程对象通信。远程对象间通信的细节由RMI处理,对于程序员来说,远程通信看起来就像标准的Java方法调用。(3)给作为参数或返回值传递的对象加载类字节码。因为RMI允许调用程序将纯Java对象传给远程对象,所以,RMI将提供必要的机制,既可以加载对象的代码又可以传输对象的数据。在RMI分布式应用程序运行时,服务器调用注册服务程序以使名字与远程对象相关联。客户机在服务器上的注册服务程序中用远程对象的名字查找该远程对象,然后调用它的方法。
使用RMI
编写Java RMI分布式应用程序的步骤主要包括以下几步:
1.将远程类的功能定义为Java接口,在Java中,远程对象是实现远程接口的类的实例。在远程接口中声明每个要远程调用的方法。远程接口具有如下特点:1)远程接口必须声明为public。如果不这样,则除非客户端与远程接口在同一个包内,否则当试图装入实现该远程接口的远程对象时会得到错误结果。2)远程对象继承java.rmi.Remote接口。3)除了所有应用程序特定的例外之外,每个方法还必须抛出java.rmi.RemoteException例外。4)任何作为参数或返回值传送的远程对象的数据类型必须声明为远程接口类型,而不是实现类。
2.编写和实现服务器类。该类是实现步骤1中定义的远程接口。所以在该类中至少要声明实现一个远程接口,并且必须具有构造方法。在该类中还要实现远程接口中所声明的各个远程方法。
3.编写使用远程服务的客户机程序。在该类中使用java.rmi.Naming中的lookup()方法获得对远程对象的引用,依据需要调用该引用的远程方法,其调用方式和对本地对象方法的调用相同。
案例 使用RMI编程
步骤:
1.为了模拟两个进程间的方法调用,在项目下分别建立client文件夹和server文件夹,用来存放client端代码和server端代码。
2.建立功能接口Hello.java,注意接口的要求,必须继承java.rmi.Remote接口,将接口复制两份,分别放在client端和server端。
packagedemo.rmi;
importjava.rmi.*;
public interfaceHello extends Remote
{
publicString sayHello(String s) throws RemotException;
}
3.在server端建立Hello接口的实现类HelloImpl。
packagedemo.rmi;
importjava.rmi.*;
import java.rmi.server.*;
public classHelloImpl extends UnicastRemoteObject implementsHello
{
publicHelloImpl() throws RemoteException{}
publicString sayHello(String s) throws RemoteException
{
return 'Echo:' + s;
}
}
4.在server端建立RMI对象注册程序,用于将HelloImpl类对象绑定到RMI服务器。
packagedemo.server;
importdemo.rmi.*;
importjava.rmi.*;
classRMIServer
{
public static voidmain(String[] args) throws Exception
{
HelloImplhi = new HelloImpl();
Naming.rebind('hello',hi);
}
}
5. 在client端建立RMIClient.java文件用来调用Hello接口的sayHello方法。
packagedemo.client;
importdemo.rmi.*;
importjava.rmi.*;
classRMIClient
{
public static voidmain(String[] args) throws Exception
{
Helloh = null;
h= (Hello) Naming.lookup('hello');
System.out.println(h.sayHello('Hello'));
}
}
6. 分编译server端的java文件。
C: empserver>mkdir buildclasses
C: empserver>javac –d build/classes src*.java
7. 在server端生成Stub和Skeleton文件,注意在新版本RMI机制下,,Skeleton文件不会被生成。因此rmic只会生成一个Stub文件。
rmic –classpath build/classes –d build/classes demo.rmi.HelloImpl
完成步骤7后,在server端的文件结构如下:
server
-src
Hello.java
HelloImpl.java
RMIServer.java
-build
-classes
-demo
-rmi
Hello.class
HelloImpl.class
HelloImpl_Stub.class
-server
RMIServer.class
8. 编译client端的java文件,之后把server端刚刚生成的Stub文件复制到client端相应的文件夹下。
C: empclient>mkdir buildclasses
C: empclient>javac –d build/classes src/*.java
完成步骤8后,在client端的文件结构如下:
client
-src
Hello.java
RMIClient.java
-build
-classes
-demo
-rmi
Hello.class
HelloImpl_Stub.class
-client
RMIClient.class
9. 运行cmd命令打开控制台,之后敲击startrmiregistry命令运行rmi服务器。再在控制台上运行RMIServer类用来注册RMI对象。这是服务器端已经准备就绪,等待客户端的远程调用。
C: empserver>start rmiregistry
C: empserver>java –classpath build/classes
-Djava.rmi.server.codebase=file://localhost/d:/temp/server/build/classes/demo.server.RMIServer
参考文献
1. (美)特尼博姆 等著;辛春生 等译《分布式系统原理与范型(第2版)》
清华大学出版社
2.罗时飞 编著 《Java网络编程精解》电子工业出版社
|