|
Rmi/Corba/Jini | Java | 2392 次查看 |
|---|---|---|
|
||
本篇用实例来说明采用Java进行RMI远程方法调用及CORBA服务调用的实现方法,并分析它们的异同,从而为分布应用软件的开发者提供参考和帮助。 Internet/Intranet的飞速发展使得Web应用日益广泛而复杂,Web早已不仅仅是超媒体信息的浏览工具,它正逐步发展成为分布异构环境中企业应用的通用前端和事务处理的展现窗口。在分布式环境异构中,各种机器所采用的操作系统、网络通信协议和应用软件千差万别,要实现信息共享和软件资源的整合十分困难,然而一个健壮的分布式计算框架能为可移植的分布式应用软件开发带来巨大的便利和好处。 分布式对象技术主要是在分布式异构环境下建立应用系统框架和对象构件。在应用系统框架的支撑下,开发者可以将软件功能封装为更易管理和使用的对象,这些对象可以跨越不同的软、硬件平台进行互操作。目前,分布式互操作标准主要有Microsoft的COM/DCOM标准、Sun公司的Java RMI标准和OMG组织的CORBA标准。 Java RMI调用实例 Java RMI简介 远程方法调用(RMI,Remote Method Invocation)是jdk1.1中引入的分布式对象软件包,它的出现大大简化了分布异构环境中Java应用之间的通信。 要使用RMI,必须构建四个主要的类:远程对象的本地接口、远程对象实现、RMI客户机和RMI服务器。RMI服务器生成远程对象实现的一个实例,并用一个专有的URL注册。RMI客户机在远程RMI服务器上查找服务对象,并将它转换成本地接口类型,然后像对待一个本地对象一样使用它。 下面是一个简单的RMI实例,RMI客户机通过RMI服务器提供的方法实现对两个双精度浮点数的加减运算。例子虽然很简单,但掌握了Java RMI调用的基本原理和方法,在实现复杂应用时,我们需要做的也只是完善远程对象的实现类而已。 RMI实例分析 1.远程对象的本地接口声明(RMIOperate.java) 该类仅仅是一个接口声明,RMI客户机可以直接使用它,RMI服务器必须通过一个远程对象来实现它,并用某个专有的URL注册它的一个实例。 具体代码如下: package wf.rmi; //包名 import java.rmi.*; //导入类包 /*RMI本地接口必须从Remote接口派生*/ public interface RMIOperate extends Remote { /*接口中的具体方法声明,注意必须声明抛出RemoteException*/ public double add(double x, double y) throws RemoteException; //输入两个浮点数,返回其和 public double minus(double x, double y) throws RemoteException; //输入两个浮点数,返回其差 } 2.远程对象实现类(OperateImpl.java) 这个类应实现RMI客户机调用的远程服务对象的本地接口,它必须从UnicastRemoteObject继承,构造函数应抛出RemoteException异常。 具体代码如下: package wf.rmi; //包名 //导入需要的类包 import java.rmi.*; import wf.rmi.RMIOperate; import java.rmi.server.UnicastRemoteObject; public class OperateImpl extends UnicastRemoteObject implements RMIOperate { /*构造函数*/ public OperateImpl() throws RemoteException { } /*实现本地接口中声明的add方法*/ public double add(double x, double y) throws RemoteException { double z = x + y; return z; } /*实现本地接口中声明的minus方法*/ public double minus(double x, double y) throws RemoteException { double z = x - y; return z; } } 3.RMI服务器类(RMIServer.java) 该类创建远程对象实现类OperateImpl的一个实例,然后通过一个专有的URL来注册它。所谓注册就是通过Java.rmi.Naming.bind()方法或Java.rmi.Naming.rebind()方法,将OperateImpl实例绑定到指定的URL上。 具体实现代码如下: package wf.rmi; //包名 //导入需要的类包 import java.rmi.Naming; import wf.rmi.OperateImpl; public class RMIServer { public static void main(String[] args) { try { //创建远程对象的实现实例 OperateImpl operObj = new OperateImpl(); //提示信息 System.out.println("RMI Server Starting..."); //将实例注册到专有的URL Naming.rebind("rmi:///RMIOperate", operObj); //等待RMI客户机调用的提示信息 System.out.println("Waiting RMI Client Invoke..."); } catch(Exception e) { e.printStackTrace(); } } } 4.RMI客户机类(RMIClient.java) RMI客户使用java.rmi.Naming.lookup()方法,在指定的远程主机上查找RMI服务对象,若找到就把它转换成本地接口RMIOperate类型。它与CORBA不同之处在于RMI客户机必须知道提供RMI服务主机的URL,这个URL可以通过rmi://host/path或rmi://host:port/path来指定,如果省略端口号,就默认使用1099。Java.rmi.Naming.lookup()方法可能产生三个异常:Java.rmi.RemoteException、Java.rmi.NotBoundException、java.net. MalformedURLException,三个异常都需要捕获。 下面是详细代码: package wf.rmi; //包名 //导入需要的类包 import java.rmi.*; import java.net.*; import java.io.*; public class RMIClient { public static void main(String[] args) { try { BufferedReader readIn = new BufferedReader(new InputStreamReader(System.in)); String host = "localhost"; //默认为本地主机 //带输入参数时,将host设置为指定主机 if (args.length > 0) host = args[0]; //根据指定的URL定位远程实现对象 RMIOperate rmiObj = (RMIOperate)Naming.lookup("rmi://" + host + "/RMIOperate"); //提示输入运算参数1 System.out.println("Please Input Data1: "); String str1 = readIn.readLine(); //读取输入参数1 double x = 0; try { x = Double.parseDouble(str1); //分析输入参数1,转换为double类型 } catch(NumberFormatException nfe) { x = 0; //如果转换异常,则重置x为0 } //提示输入运算参数2 System.out.println("Please Input Data2: "); String str2 = readIn.readLine();//读取输入参数2 double y = 0; try { y = Double.parseDouble(str2); //分析输入参数2,转换为double类型 } catch(NumberFormatException nfe) { y = 0; //如果转换异常,则重置y为0 } //调用远程对象的本地接口方法,实现输入参数的加、减运算,并输出结果 System.out.println("Data1 Add Data2 Result is: " + rmiObj.add(x, y)); System.out.println("Data1 minus Data2 Result is: " + rmiObj.minus(x, y)); } catch(Exception e) { e.printStackTrace(); } } } RMI Server/Client的编译与运行 (1).编译所有的源代码(如图1) ![]() 图1 (2).生成客户端存根和服务器框架(如图2) ![]() 图2 这将构造OperateImpl_Stub.class和OperateImpl_Skel.class。这时可将所有的Class文件打包成jar,并将其分别置于RMI客户机和RMI服务器的ClassPath中(如图3): ![]() 图3 当然,也可以只将RMIOperate.class、RMIClient.class和OperateImpl_Stub.class复制到RMI客户机,将RMIOperate.class、OperateImpl.class 、RMIServer.class和OperateImpl_Skel.class复制到RMI服务器。 (3).启动RMI注册(如图4) ![]() 图4 (4).运行和调用 ● 在服务器上执行RMIServer(如图5) ![]() 图5 ● 在本地客户机上运行RMIClient(如图6) ![]() 图6 ● 在远程客户机上运行RMIClient(须指明RMI服务器主机名或IP地址,如图7) ![]() 图7 至 |
||