维普资讯 http://www.cqvip.com 开放系统世界 ■ [Java] 开发进阶 一 ・RMI与CORBA 长碥… f々lj妊说 .果}手j J叭 a进“RM1远稚方法 川技 (t)ItB.\搬务 戈观, 憾.垮,}机它{fj的蚌 . 坼i j ☆j| {耆 f'l:的J| 镟嚣提供参考f¨帮渤 Ii ̄terl,et//Intranet的飞速发展使得Web应用日益广泛而 复杂,Web早 小仅仗是超媒体信息的浏览工具,它正逐步 发展 为分 构环境中企业应用的通用前端和事务处理的 畏 窗I]。 分布式环境异构中,各种机器所采用的操作系 统、网络通信协议和应用软件干差万别,要实现信息共享和 软件资源的整合 分困难,然而一个健壮的分布式计算框架 能为町移植的分布式应用软件开发带来巨人的便利和好处。 分布式对象技术土要是在分布式异构环境下建立 用系 境眶架和对象构件。住应用系统框架的支撑F,开发者可以 lI孑软件功能封装为更易管理和使用的对象,这些对象可以跨 越 同的软、硬件平台进行互操作。目前,分布式互操作标 蠹主要有Microsoft的COM/DCoM标准、Sun公司的Java RMI标准和oⅥG组织的CoRBA标准。 java RM|简介 远程方法调用(RMI,Remote Method InvocaLion)是 jdk1.1中引入的分布式对象软件包,它的出现大大简化了分 布异构环境中Java应用之间的通信。 要使用RMI,必须构建四个主要的类:远程对象的本地 接L]、远程对象实现、RMI客户机和RMI服务器。RMI服 务器生成远程对象实现的一个实例,并用一个专有的URL注 册。RMI客户机在远程RMI服务器上查找服务对象 并将它 转换成本地接L]类型,然后像对待一个本地对象一一样使用它。 下面是一个简单的RMI实例,RMI客户机通过RMI服 务器提供的方法实现对两个双精度浮点数的加减运算。例子 虽然很简单,但掌握了Java RMI调用的基本原理和方法,在 实现复杂应用时,我们需要做的也只是完善远程对象的实现 ◇文枫 类而已。 RMI实铫分析 1 远程x,l象的本地接L==I声明(RMIOperate.java) 该类仅仅是一个接口声明,RMI客户机可以直接使用它, RMI服务器必须通过一个远程对象来实现它,并用某个专有 的URL注册它的一个实例。 具体代码如下: package wf rmi;,,包.煞 import java.rmi, ;//导入类包 /十RMI本地接口必须从Remote接口派生十/ public interface RM10Derate extends Remote { /+接口中的具体方法声明,注意必须声明抛出 Remote! ̄:xception*/ public double add(double X,double Y)throws RemoteException;//输入两个浮点数,返回其和 public double minus(double X,double Y)throws RemoteException;//输入两个浮点数,返回其差 ) 2.远程对象实现类(OperateImpl+java) 这个类应实现RMI客户机调用的远程服务对象的本地接 L],它必须从UnicastRemoteObject继承,构造函数应抛出 RemoteException异常。 具体代码如一卜: package wf.rmi;//包名 //-9入需要的类包 impo ̄java.rmi. ; impo ̄wI.rmi.RMICIperate; impo ̄java.rmi.server.UnicastRemoteObject; public class OperateImpl extends UnicastRemoteObject implements RM10’perate 维普资讯 http://www.cqvip.com 一囊[Java] 开发进阶■一 ・//创建远程对象的实现实例 /・构造函数・/ Operatelmpl operObj=new OperateImpl(); //强际信息 System.out.println(’,RlVlI Server Starting…”); //将实例注册到专有的URL Naming.rebind(”rmi:// MIOperate",operObj); public OperateImpl()throws RemoteException { } /・实现本地接口中声明的add方法・/ public double add(double x,double y)throws RemoteException //等待RMI客户机调用的提示信息 System。out。println(”Waiting RMI elient Invoke…”); } { double z=Xreturn Z: +y; catch(Exception e) { e.printStackTrace0; } } /・实现本地接口中声明的minus方法・/ } } pubic double minus(double x,double y)throws RemoteException { double z=xreturn Z; 4.RMI客户机类—y; (RMIClient.java) RMI客户使用java.rmi.Naming.1ookup()方法,在指 定的远程主机上查找RMI服务对象,若找到就把它转换成本 地接口RMIOperate类型。它与CORBA不同之处在于RMI 客户机必须知道提供RMI服务主机的URL,这个URL可以 通过rmi://host/path或rmi://host:po ̄/path来指定,如 } } 3.RMI服务器类(RMIServer.java) 果省略端口号,就默认使用1099。Java.rmi.Naming.1ookup ()方法可能产生三个异常:Java.rmi.RemoteException、 J aVa.rmi.NOtB OUndExcePtiOn、J av a.net. 该类创建远程对象实现类Operatelmpl的一个实例,然后 通过一个专有的U R L来注册它。所谓注册就是通过 Java.rmi.Naming.bind()方法或Java.rmi.Naming.rebind MaLformedURLException,三个异常都需要捕获。该类详细 代码见http://linux.ccidnet.corn期刊浏览第9期 £)方法,将Operatelmpl实例绑定到指定的URL上。 具体实现代码如-y: package .rmi;//包名 RMI Server/Client的编译与运行 (1).编译所有的源代码(如图1) //导入需要的类包 import java.rmi.Naming import wf.rmi Operatelmpl; 图1 pubic class RMIServer (2).生成客户端存根和服务器框架(如图2) { public static void main(String[]ar ̄s) { ny 图2 这将构造O P e r a t e I m P l—S t u b.c l a s s和 Operatelmpl_Ske1.class。这时可将所有的Class文件打包成 { 硼绷隧辣0 。 I0| jl l9…7 维普资讯 http://www.cqvip.com 开放系统世界 一 [Java]臻j ・开发进阶 ■ jar,并将其分别置于RMI客户机和RMI服务器的ClassPath 中(如图3): CORBA基本介绍 CORBA(通用对象请求代理体系结构)是oMG(对象 管理组织)于l991年提出的基于对象技术的分布计算应用软 件体系结构。CORBA标准主要分为三个部分:接口定义语 言(IDL)、对象请求代理(ORB),以及ORB之间的互操作 协议IIOP,核心是对象请求代理。CORBA可以抽象系统平 图3 台、网络通讯及编程语言的差异。通过在CORBA技术规范 中定义多种类型的服务,如名字服务(Naming Service)、事 当然,也可以只将RMIOperate.class、RMIClient.class 务服务(Transaction Service)、对象生命期服务(LifeCycle Service)、并发控制服务时间服务一和OperateImpl_Stub.Class复制到RMI客户机,将 RMIOperate.class、 OperateImp1.class 、 RMIServer.class (Concurrency Control Service)、 (Time Service)等功能,为应用软件开发者提供 和OperateImpl_Ske1.class复制到RMI服务器。 (3).启动RMI注册(如图4) 个全面、健壮、可扩展的分布对象计算平台,使面向对象 的应用软件在分布异构环境下方便地实现可重用、易移植和 互操作。 图4 采用,Java 建CORBA应用 (4).运行和调用 ・在服务器上执行RMIServer( ̄[1图5) CORBA对象服务的实现方式分为两种:对象的命名引 用方式和字符串化对象引用方式。不论采用何种高级语言, 刨建CORBA应用程序的过程大体如下: ・进行系统分析,确定服务对象需要提供的功能; 图5 ・根据分析结果,编写IDL接口说明文件; ・将接口说明文件编译为相应高级语言源代码,产生服务 ・在本地客户机上运行RMIClient( ̄[1图6) 器框架与客户端存根: ・基于服务器框架,编写服务对象实现程序; ・基于客户端存根,编写客户对象调用程序; ・分别编译客户对象和服务对象程序; ・启动服务对象程序; 图6 ・启动客户对象程序。 ・在远程客户机上运行RMIClient(须指明RMI服务器 CORBA实例分析 下面通过一个实例,描述如何通过Java刨建CORBA应 用程序,并比较其与Java RMI应用程序的异同。 假设要通过CORBA实现与上面Java RMI所描述的相 同应用,我们该如何开始呢? 首先,编写IDL接口说明文件(Test.id1): 主机名或IP地址,如图7) 图7 module test f 至此,RMI调用完成。完整的源代码请参见http:// Linux.ccidnet.corn的期刊浏览第9期。 interface operate f 维普资讯 http://www.cqvip.com ●●[Java] 开发进阶●● ・doub ̄add(in double a,in double b); double minus(n doublie a,in doub ̄b); }; ); double z=X+y; return z: 然后,通过Sun提供的将IDL文件编译成Java源代码的 [具idlj(jdk1.3.0—01以上版本),为接口定义文件生成客户 /・实现接口声明方法minus*/ public double minus(double x,double Y) { double z=X—y; 错存根和服务器框架。具体操作如下(如图8): 图8 return z; ) f参数指明生成内容,all包括客户端存根和服务器框 品,这样在当前目录下生成一个test目录。其目录下将包括 F歹U文件(女口图9): 在此基础上,再编写服务对象程序。为了方便实现服务端的多线程调用,我们实现了Runnable接口。具体代码如下: 。 package wf.corba;//包笔 /幸弓I_入类包・/ imDort org.omg.CORBA, ; j import org.omg.CosNaming. ; imDortjava.net.’; .一 /・服务端实现了Runnable接口,以便多线程扩展 / 图9 ublpic class CORBAServer implements Runnable i 通过这些文件,就可以编写服务对象实现程序和客户对 良调用程序了。 / 构造函数・/ 薯 public CORBAServer(Strin ̄(注意:该类需从 args) 为保iiE IDL接口说明文件中声明的方法能被调用,首先 旨要实现该接口。具体代码如下operatelmplBase派生): irdtORB(args); 、 毫 package wf.corba;//包名 import test.’;//引入类包 /≈初始化0RB*/ private void initORB(fltring[]args) public class OperateImpl extends_operateImplBase { /・构造函数・/ public Operatelmpl() { super(); } try ’ 0 : 。 //褥摄 鹋妊盼 钰纯潞|- -1 | ORB orb-,=ORB ̄t(args,nul1);//耨 个酸务寥徽氟 .薯≮ |■ l键 鼍|t 毪鬟誊j毫一 Operatelmpl 漱一掰潮 , :奢疆巍 一 薯霉;警鼍霞 晒 皓 //连接该服务实现艨 /・实现接口声明方法add*/ 00 0 _ : Il _●挚 ≯ 薯t≈尊m t薯≈ orb connect(operateRef); //{II晰 字弓、甩 public double add(double x,double y) || ll!| 鼍| 搠赚 蕾 ◇ ≯0 囊 维普资讯 http://www.cqvip.com 开放系统世界 一嚣[Java]蕾 开发进阶 ■ ・0rg.0mg.C0RBA.0bject 0bjRef: orb.resolve_initial_references(.NameService.); //匹配CORBA对象 N a m i n g C O n t e x t n c R e f = CORBAServer CS= new CORBAServer(args); //运行CORBA服务对象 cs.run(); NamingContextHelper.narrow(objRef); //新建指定接口模块名的名字组件 NameComponent nc=new NameComponent (”test",…f); 最后编写客户端调用程序。具体代码请参见http:// linux.ccidnet.corn的期刊浏览第9期。 NameComponent path[]={nc}; //根据名字服务绑定CORBA服务对象 ncRef.rebind(path,operateRef); } catch(Exception e) { e.printStackTrace(); } ) 到这里,我们已创建了 ̄CORBA应用所需要的所有服务 器和客户机对象,接着运行它,看是否可以实现预想的功能。 CORBA ServerJClient的编译与运行 1.编译所有的Java源文件(如图10): 2.启动Sun提供名字服务器(可通过ORBInitiaPort设 /・实现Runnable接口・/ public void run() { try 图10 定其端口,默认为900,本例中为10050)(如图11) { //输出系统提示信息 System.out.println(.CORBA Server Host:”+ InetAddress.getLocalHost0.getHostAddress()+”,Port: 1OO5O\nCoRBA Server Ready,Waiting Client Invoke 图ll Now…”); java.1ang.Objeat objeat=new java.1ang.Object (); 3.启动本例中实现的CORBA服务对象test(Rtl图12) //同步对象,等待客户调用 synchronized(object) { 图l2 4.CORBA客户机在本地调用CORBA服务(如图13) object.wait(); } } atch(Excception e) { e.printStackTrace(); } } 图l3 5.CORBA客户机在运程调用CORBA服务(如图14) /・主人口函数・/ public static void main(String[】args) 图l4 维普资讯 http://www.cqvip.com 一 [Java]警 i・开发进阶 ■ 由上可见,在远程调用时,CORBA客户机需要知道服 { 务对象的主机名(或IP,通过ORBInitialtlost参数指定)和 端口(可通过ORBInitialPort参数指定);而在本地调用时, 只需要指明服务端口即可。 e.printStackTraceO; } } 通过Applet调用CORBA服务 在很多情况下,我们不但希望通过客户端程序调用 CORBA服务,而且还希望将其嵌入Applet中。由于Java Applet采取“Sand-Box”安全模型,使得Java Applet既 通过浏览器可以直接运行,也可以通过Appletviewer查 看运行结果(如图15)。 不能与宿主机以外的计算机建立网络连接,也不能访问本地 文件系统和设备。CORBA系统的特点是服务对象的分布性 和远程对象定位的透明性。本地系统可通过C0RBA规范提 供的IIOP代理(Gatekeeper)来解决安全的约束,它负 责接收Applet发来的IIOP报文,分析报文内容,将其转发 给位于其它主机上的无法直接 Applet调用的C0RBA服务 对象实现,并将服务对象返回的IIOP报文提交给Applet,从 而完成C0RBA服务调用。 下面给出通过Appleti ̄问本例中CORBA服务对象的主 要实现代码。 public class ClientApplet extends lApplet implements Ac虹on王 g£ener { private void initORB0 { try { 图l5 //定义参数数组,指明coRBA服务对象主机和端口 String args[】一fII—ORBInitialHostIl, lI10.16.93.39lI,tt—oRBInitialPort.,t loo5Ot }; ORB orb=ORB.init(args,nul1);//根据指定参 数进行ORB初始化 与c0RBA相比, 功能较弱且只能用于Java系统。 RMI可以直接把分布式对象模型嵌入到Java语言内部,使得 Java程序员可以方便、快捷地编写分布式程序,而不必离开Java 环境,或者涉及C0RBA的I【)L,以及Java到CORBA的数据 类型映射与转换。但是, = //解析根名字引用 Org.Omg.CORBA.Object ObjRef = orb.resolvejI1i缸al_references('!NameService',); N a m i n g C 0 n t e x t n c R e f 不遵守CORBA标准,基本上是 Java-to-Java技术,它需要客户端程序和服务器程序都用Java NamingContextHelper.narrow(objRef); NameComponent nc=new NameComponent 编写,所以难以实现与其它语言编写的对象之间的互操作。。 CORBA则灵活、强大许多,其客户机与服务器可以根据需要采用不同的高级语言来开发和编写,并且抽象了分布系统中远程方法调用的内在复杂性,提供了分布异构环境中的应用对象 集成和互操作的软件总线。因此,在实际分布应用开发中,我嚣 簿 _ (test'!,lfl ); NameComponent path[】={nc}; opRef=operateHelper.narrow(ncRef、resolve (path)); } 们应该根据具体的情况来决定采用RMI还是CORBA。总之, 毒 RM1只能是Java对象之间的互操作,功能较为简单,实现也比较容易;CORBA则更适合于大型异构系统之间的复杂应用整 合,开发的代价相对要高一些。瑗 j一 catch(Exception e) 蠢 开取系统世界 JDl