??xml version="1.0" encoding="utf-8" standalone="yes"?>欧美精品久久久久久久多人混战
,久久精品黄色,亚洲免费一区http://www.aygfsteel.com/liujw/articles/39151.html刘军?/dc:creator>刘军?/author>Tue, 04 Apr 2006 05:50:00 GMThttp://www.aygfsteel.com/liujw/articles/39151.htmlhttp://www.aygfsteel.com/liujw/comments/39151.htmlhttp://www.aygfsteel.com/liujw/articles/39151.html#Feedback0http://www.aygfsteel.com/liujw/comments/commentRss/39151.htmlhttp://www.aygfsteel.com/liujw/services/trackbacks/39151.html1997 (tng)q_(d)IBM (tng)和?tng)Sun (tng)Microsystems (tng)启动?jin)一Ҏ(gu)在促(j)q?tng)Java (tng)作ؓ(f)企业开发技术的发展的合作计划。两家公司特别着力于如何?tng)Java (tng)用作服务器端语言Q生成可以结合进现有体系l构的企业代码。所需要的是一U远E传输技术,它兼有?tng)Java (tng)的?tng)RMIQRemote (tng)Method (tng)I(yng)nvocationQ远E方法调用)(j)较少的资源占用量和更成熟的?tng)CORBAQCommon (tng)Object (tng)Request (tng)Broker (tng)ArchitectureQ公共对象请求代理体pȝ构)(j)技术的健壮性。出于这一需要,RMI-IIOP (tng)问世?jin),它帮助将?tng)Java (tng)语言推向?jin)目前服务器端企业开发的L语言的领先地位?br />
在本文中Q我简要介l?tng)RMI-IIOPQ目标是使?zhn)能开始在企业开发解x(chng)案中使用q一技术。要解释 (tng)RMI-IIOP (tng)I竟是什么,我认为提供一些关于?tng)CORBA (tng)和?tng)RMI (tng)的信息是重要的,q些信息(zhn)在各个技术的典型介绍中可能找不到。如果?zhn)对 (tng)CORBA (tng)或?tng)RMI (tng)的基知识不熟(zhn),我徏议?zhn)在往(xin)下读之前先阅M些介l性信息。请参阅 (tng)参考资料,那里?xi)选了(jin)一些文章和教程。?br />
在我具体讨论 (tng)RMI-IIOP (tng)之前Q我们将先看一下?tng)CORBA (tng)和?tng)RMI (tng)用来对请求进行数据编入的机制。CORBA (tng)是我们的主要示例,因ؓ(f) (tng)RMI-IIOP (tng)数据~入是徏立在 (tng)CORBA (tng)传输协议QIIOPQ的基础上的。我们将回顾一下该传输协议和?tng)ORBQobject (tng)request (tng)brokerQ对象请求代理)(j)在网l上发送请求、定位远E对象和传输对象斚w的基本功能?br />
q程对象传输
对?tng)CORBA (tng)hq行数据~入是通过使用 (tng)I(yng)IOP (tng)协议做到的。简a之,IIOP (tng)以标准化格式构造的M (tng)I(yng)DLQInterface (tng)Definition (tng)LanguageQ接口定义语aQ的元素表示Zpd字节。那假设有一个?tng)Java (tng)客户机正在将一个?tng)CORBA (tng)h分派刊WC++ (tng)服务器吧。客h应用E序以?tng)Java (tng)接口的Ş式拥有远E对象的引用Qƈ调用该接口的一个操作。本质上是,接口调用它对该操作的相应实现Q这个实现将位于存根QstubQ(存根是?zhn)已l用 (tng)idlj (tng)从?tng)I(yng)DL (tng)生成?jin)的Q。?br />
存根把方法调用分zֈ (tng)ORB (tng)中,ORB (tng)׃部分l成Q客h (tng)ORB (tng)和服务器 (tng)ORB。客h (tng)ORB (tng)的职责是对请求进行数据编入,攑ֈ|络上,传往(xin)特定位置。服务器 (tng)ORB (tng)的职责是侦听从网l上传下来的hQƈ这些请求{换成语言实现能够理解的方法调用。要?jin)解对 (tng)CORBA (tng)ORB (tng)的角色的更深入讨论,请参阅?tng)参考资料部分。?br />
存根分派?jin)方法调用之后,客户机 (tng)ORB (tng)请求和所有参数{换成标准化字节格式,在这U情况中是?tng)I(yng)IOP。接着Q请求通过导线被发送到服务器?tng)ORBQ服务器 (tng)ORB (tng)应该正在侦听传入h。服务器端?tng)ORB (tng)读q数据的字节q将h转换成对 (tng)C++ (tng)服务器实现有意义的东ѝC++ (tng)服务器方法将执行它的功能Q即调用所h的方法)(j)q用相同的机制通过 (tng)I(yng)IOP (tng)结果返回给客户机?br />
RMI (tng)以类似的方式处理hQ但是它使用 (tng)JRMPQJava (tng)Remote (tng)Messaging (tng)ProtocolQJava (tng)q程消息传递协议)(j)作ؓ(f)其传输协议。当?dng)RMI (tng)传输q涉?qing) (tng)Java (tng)对象的序列化?br />
(tng)CORBA (tng)和?tng)RMI (tng)的差?br />
CORBA (tng)q行在?tng)I(yng)IOP (tng)协议之上QRMI (tng)使用 (tng)JRMP。?br />CORBA (tng)是独立于语言的;RMI (tng)是纯_?tng)Java (tng)刊WJava (tng)的。?br />RMI (tng)使用 (tng)JNDI (tng)定位q程对象QCORBA (tng)使用 (tng)CosNaming。?br />RMI (tng)?x)将对象序列化;CORBA (tng)则不然。?br />
(tng)q程对象定位
CORBA (tng)使用 (tng)CosNaming (tng)命名服务定位q程对象。CosNaming (tng)为名U服务器保存对?tng)CORBA (tng)服务器进E的l定Q或引用Q提供了(jin)一个框架。当 (tng)CORBA (tng)客户机向名称服务发送?tng)CosNaming (tng)hQ请求给定名U的服务器进E时Q名U服务返回该q程的?tng)可互操作对象引用(interoperable (tng)object (tng)referenceQIORQ)(j)。接着Q客h使用该?tng)I(yng)OR (tng)直接与服务器q程通信。?br />
IOR (tng)包含关于服务器进E的信息Q例如服务器q程的位|。CosNaming (tng)服务的缺点之一是,IOR (tng)对hc而言是难以看懂的 (tng)—?tng)至对我们q些没有?sh)子大脑的h来说是这栗相反地QRMI (tng)对用户则要友好一些。它使用q行在?tng)JNDI (tng)之上的?tng)注册中心(j)(与命名服务极为相|(j)来定位远E对象。RMI (tng)注册中心(j)使用 (tng)Java (tng)Reference (tng)对象Q它pq个 (tng)RefAddr (tng)对象l成Q来识别和定位远E对象。这些?tng)Java (tng)对象比?tng)I(yng)OR (tng)对用h加友好。?br />
不久前,COBRA (tng)可互操作命名服务(Interoperable (tng)Naming (tng)ServiceQINSQ)(j)l合q了(jin)它的对象-定位Qobject-locationQ模式。INS (tng)在?tng)CosNaming (tng)上运行,使用人类可以阅读的?tng)URL (tng)作它的对象位|。INS (tng)不用命名服务;相反圎ͼ它将调用直接发送到指定的?tng)URL。请参阅 (tng)参考资料了(jin)解关于?tng)I(yng)NS (tng)的更多信息。?br />
RMI (tng)对?tng)CORBA
那么Q哪一个更好呢Q是 (tng)CORBA (tng)q是 (tng)RMIQ答案取决于(zhn)想做什么。CORBA (tng)是一个运行在业界标准的第三或W四代协议上的、经q试验和试的大体系l构。如果考虑刊WCORBA (tng)提供的所有附Ӟ例如Q事务处理、安全拦截器、事仉道Q还有更多)(j)的话Q则 (tng)CORBA (tng)看来是企业应用程序的解决Ҏ(gu)。CORBA (tng)的最大缺Ҏ(gu)它很复杂。要熟练使用 (tng)CORBAQ开发者通常要经历陡峭的培训曲线?br />
相反圎ͼRMI (tng)相当Ҏ(gu)学习(fn)。创Z个客hQ服务器实现Q绑定到注册中心(j)和远E对象,使用 (tng)RMI (tng)调用和/或接收请求都相当单。RMI (tng)的资源占用量也比 (tng)CORBA (tng)得多,因ؓ(f) (tng)JRMP (tng)是开销比?tng)I(yng)IOP (tng)得多的协议。但是,RMI (tng)~Z (tng)CORBA (tng)的工业的附Ӟ而且是纯Z (tng)Java (tng)的机制。那么,我们真正需要的是 (tng)RMI (tng)的灵zL和易用性以?qing) (tng)CORBA (tng)的企业就l性,对吗Q那开始讨论?tng)RMI-IIOP (tng)吧?br />
(tng)Z么是 (tng)RMI-IIOPQ?br />
RMI-IIOP (tng)兼有 (tng)CORBA (tng)的强度和 (tng)RMI (tng)的灵zL。?br />开发者很Ҏ(gu)可以用?tng)RMI-IIOPQRMI-IIOP (tng)也易于集成到多数企业基础架构中。?br />
(tng)
RMI-IIOP (tng)概览
RMI-IIOP (tng)让?zhn)仅需极少修改可以在 (tng)I(yng)IOP (tng)上运行?tng)RMI (tng)调用。借助于?tng)RMI-IIOPQ?zhn)可以~写单易懂的 (tng)Java (tng)代码Q同时用?tng)CORBA (tng)提供的丰富的企业功能套g。而且Q代码的灉|性够大Q可以运行在 (tng)RMI (tng)或IIOP (tng)上。这意味着Q?zhn)的代码可以在U?tng)Java (tng)环境中运行(当小的资源占用量和灵zL很关键Ӟ(j)Q或者对代码作少量修改后集成到现有的 (tng)CORBA (tng)基础架构中。?br />
RMI-IIOP (tng)很强大的功能之一是,它让(zhn)编写纯 (tng)Java (tng)客户机/服务器实现而不丧失 (tng)RMI (tng)cd列化的灵zL。RMI-IIOP (tng)通过覆盖 (tng)Java (tng)序列化ƈ在导U上?tng)Java (tng)c{换成 (tng)I(yng)IOP (tng)做到q一炏V在另一端,Java (tng)c被作ؓ(f) (tng)I(yng)IOP (tng)从导U上M来,接着创徏q个cȝ一个新实例Q用反)(j)Q类的所有成员的值都完整无缺 (tng)—?tng)瞧Q这是 (tng)I(yng)IOP (tng)上的 (tng)Java (tng)序列化! (tng)
Z(jin)让?tng)RMI-IIOP (tng)实现透明的对象定位,ORB (tng)供应商历史上曄使用 (tng)Java (tng)CosNaming (tng)服务提供者(或用外行人的话说Q是 (tng)插gQ。该插g在?tng)JNDI (tng)API (tng)之下工作Q访问?tng)CORBA (tng)命名服务。尽我没有在这里花幅来说明原因,但这U命名解x(chng)案ƈ不理惟뀂其l果是,许多供应商?tng)—?tng)尤其是应用服务器供应商?tng)—?tng)?f) (tng)RMI-IIOP (tng)开发了(jin)专门的对象定位机制。?br />
RMI-IIOP (tng)也支持作为?tng)Java (tng)CosNaming (tng)服务的一个扩展的 (tng)I(yng)NS。因为我怿 (tng)I(yng)NS (tng)确定对象定位的未来方向Q所以我们在本文讨论的代码CZ使用 (tng)I(yng)NS?br />
注:(x)因ؓ(f) (tng)Sun (tng)未完全遵@ (tng)OMG (tng)I(yng)NS (tng)标准Q也未公开 (tng)org.omg.CORBA.ORB (tng)接口的?tng)register_initial_reference (tng)Q所以本文提供的源代码将不能与?tng)Sun (tng)JDK (tng)一起工作。?zhn)需要?tng)I(yng)BM (tng)Developer (tng)Kit (tng)for (tng)Java (tng)technologyQ版本?.3.1 (tng)或更高版本。不q,我已l创Z(jin)一个用命名服务的与?tng)Sun (tng)兼容的示例,(zhn)可以从 (tng)参考资料部分下载它 (tng)
自己动手构徏 (tng)RMI-IIOP
说得够多?jin),让我们来~写代码吧!在以下几部分中,我们构Z个简单的、基于?tng)Java (tng)的客hQ服务器 (tng)RMI-IIOP (tng)应用E序。这个应用程序由三个部分l成QRMI (tng)接口、服务器应用E序和客h应用E序。示例以在?tng)I(yng)IOP (tng)之上的?tng)Java (tng)序列化ؓ(f)特色Q所以?zhn)可以看到?tng)Java (tng)cd何被客户机实例化Q如何传递到服务器,由服务器更改Q然后将所有修改完整地回传到客h?br />
W? (tng)部分Q定义接?br />
在?tng)RMI-IIOP (tng)下,我们可以选择使用 (tng)RMI (tng)或?tng)I(yng)DL (tng)来定义接口。因为我们想看看 (tng)RMI (tng)如何q行在?tng)I(yng)IOP (tng)上,所以我们将使用 (tng)RMI (tng)定义CZ接口。清单? (tng)是我们的单示例的 (tng)RMI (tng)接口Q?br />
清单 (tng)1. (tng)RMIInterface.java
/*
(tng)* (tng)Remote (tng)interface
(tng)*/
public (tng)interface (tng)RMIInterface (tng)extends (tng)java.rmi.Remote (tng){
(tng) (tng) (tng) (tng)public (tng)String (tng)hello() (tng)throws (tng)java.rmi.RemoteException;
(tng) (tng) (tng) (tng)public (tng)SerClass (tng)alterClass(SerClass (tng)classObject) (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng)throws (tng)java.rmi.RemoteException;
}
(tng)
RMIInterface (tng)定义一个?tng)hello() (tng)Ҏ(gu)和一个?tng)alterClass(SerClass) (tng)Ҏ(gu)。后一个方法用 (tng)SerClass (tng)作参敎ͼ (tng)SerClass (tng)是一个实玊WSerializable (tng)的?tng)Java (tng)c, (tng)alterClass(SerClass) (tng)Ҏ(gu)q回一个类型与其参数的cd相同的类。?tng)SerClass (tng)是一个有几个成员的简单的c,每个成员有相应的 (tng)getter (tng)Ҏ(gu)。这些方法如清单 (tng)2 (tng)所C:(x) (tng)
清单 (tng)2. (tng)SerClass.java
/**
(tng)* (tng) (tng)This (tng)class (tng)is (tng)intended (tng)to (tng)be (tng)serialized (tng)over (tng)RMI-IIOP.
(tng)*/
public (tng)class (tng)SerClass (tng)implements (tng)java.io.Serializable (tng){
(tng) (tng) (tng) (tng)// (tng)members
(tng) (tng) (tng) (tng)private (tng)int (tng)x;
(tng) (tng) (tng) (tng)private (tng)String (tng)myString;
(tng) (tng) (tng) (tng)// (tng)constructor
(tng) (tng) (tng) (tng)public (tng)SerClass(int (tng)x, (tng)String (tng)myString) (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng)throws (tng)java.rmi.RemoteException (tng){
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)this.x=x;
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)this.myString=myString;
(tng) (tng) (tng) (tng)} (tng)
(tng) (tng) (tng) (tng)
(tng) (tng) (tng) (tng)// (tng)some (tng)accessor (tng)methods
(tng) (tng) (tng) (tng)public (tng)int (tng)getX() (tng){ (tng) (tng)return (tng)x;}
(tng) (tng) (tng) (tng)public (tng)void (tng)setX(int (tng)x) (tng){ (tng)this.x=x; (tng)}
(tng) (tng) (tng) (tng)public (tng)String (tng)getString() (tng){ (tng) (tng)return (tng)myString; (tng) (tng)}
(tng) (tng) (tng) (tng)public (tng)void (tng)setString(String (tng)str) (tng){ (tng)myString=str; (tng)}
}
(tng)
q就是我们简单的接口的全部。现在我们来研究一下服务器cR?br />
W? (tng)部分Q构建服务器
我们用一个既充当 (tng)RMIInterface (tng)实现cd包含 (tng)main (tng)Ҏ(gu)Q以启动我们的服务)(j)的服务器c( (tng)Server.java (tng)Q。?tng)Server.java (tng)l承 (tng)javax.rmi.PortableRemoteObject (tng)。这P它就包含?jin)将自己作?f) (tng)Remote (tng)接口l定刊WORB (tng)和开始侦听请求所需要的全部功能。清单? (tng)是该服务器的代码Q?br />
清单 (tng)3. (tng)Server.java
/*
(tng)* (tng)Simple (tng)server
(tng)*/
import (tng)java.util.*;
import (tng)java.rmi.Remote;
import (tng)java.rmi.RemoteException;
import (tng)javax.rmi.PortableRemoteObject;
import (tng)javax.rmi.CORBA.Tie;
import (tng)javax.rmi.CORBA.Util;
import (tng)org.omg.PortableServer.POA;
import (tng)org.omg.PortableServer.*;
import (tng)org.omg.PortableServer.Servant;
import (tng)org.omg.CORBA.ORB;
public (tng)class (tng)Server (tng)extends (tng)PortableRemoteObject (tng)
(tng) (tng) (tng) (tng)implements (tng)RMIInterface (tng){
(tng) (tng) (tng) (tng)// (tng)must (tng)explicitly (tng)create (tng)default (tng)constructor (tng)
(tng) (tng) (tng) (tng)// (tng)to (tng)throw (tng)RemoteException
(tng) (tng) (tng) (tng)public (tng)Server() (tng)throws (tng)RemoteException (tng){
(tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng)// (tng)implementation (tng)of (tng)RMIInterface (tng)methods
(tng) (tng) (tng) (tng)public (tng)String (tng)hello() (tng)throws (tng)RemoteException (tng){
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return (tng)"Hello (tng)there!";
(tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng)public (tng)SerClass (tng)alterClass(SerClass (tng)classObject) (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)throws (tng)RemoteException (tng){
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)// (tng)change (tng)the (tng)values (tng)of (tng)SerClass (tng)and (tng)return (tng)it.
(tng) (tng) (tng) (tng)// (tng)add (tng)5 (tng)to (tng)X
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)classObject.setX( (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)classObject.getX() (tng)+ (tng)5 (tng)); (tng)
(tng) (tng) (tng) (tng)// (tng)alter (tng)the (tng)string
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)classObject.setString( (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)classObject.getString() (tng)+ (tng)" (tng): (tng)I(yng)'ve (tng)altered (tng)you" (tng)); (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)return (tng)classObject;
(tng) (tng) (tng) (tng)} (tng) (tng) (tng)
(tng) (tng) (tng) (tng)public (tng)static (tng)void (tng)main(String[] (tng)args) (tng){
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)try (tng){
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)// (tng)create (tng)the (tng)ORB (tng)passing (tng)in (tng)the (tng)port (tng)to (tng)listen (tng)on
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)Properties (tng)props (tng)= (tng)new (tng)Properties();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)props.put("com.ibm.CORBA.ListenerPort","8080");
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)ORB (tng)orb (tng)= (tng)ORB.init(args, (tng)props);
(tng) (tng) (tng) (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)// (tng)instantiate (tng)the (tng)Server
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)// (tng)this (tng)will (tng)automatically (tng)call (tng)exportObject(this)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)Server (tng)s (tng)= (tng)new (tng)Server();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)// (tng)now (tng)get (tng)the (tng)Stub (tng)for (tng)our (tng)server (tng)object (tng)- (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)// (tng)this (tng)will (tng)be (tng)both
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)// (tng)a (tng)remote (tng)interface (tng)and (tng)an (tng)org.omg.CORBA.Object
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)Remote (tng)r=PortableRemoteObject.toStub(s); (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)
(tng) (tng) (tng) (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)// (tng)register (tng)the (tng)process (tng)under (tng)the (tng)name (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)// (tng)by (tng)which (tng)it (tng)can (tng)be (tng)found (tng) (tng) (tng) (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)((com.ibm.CORBA.iiop.ORB)orb).
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)register_initial_reference("OurLittleClient",
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)(org.omg.CORBA.Object)r);
(tng) (tng) (tng) (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)System.out.println("Hello (tng)Server (tng)waiting...");
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)// (tng)it's (tng)that (tng)easy (tng)- (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)// (tng)we're (tng)registered (tng)and (tng)listening (tng)for (tng)incoming (tng)requests
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)orb.run();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} (tng)catch (tng)(Exception (tng)e) (tng){
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)e.printStackTrace();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng)}
}
(tng)
呃,q里发生着什么呢Q?br />
服务器应用程序的代码很长Q那我们分开来讲吧。首先,如前面提到过的, (tng)Server (tng)cd玊WRMIInterface (tng)qؓ(f)它的所有方法提供实现。?zhn)可以在代码的前面部分看到?tng)RMIInterface (tng)的?tng)hello() (tng)Ҏ(gu)和?tng)alterClass(SerClass) (tng)Ҏ(gu)的实现。?tng)hello() (tng)Ҏ(gu)只是q回字符东y(c)Hello (tng)there!”。?tng)alterClass(SerClass) (tng)Ҏ(gu)用?tng)SerClass (tng)对象作参敎ͼ修改成员的|然后q回新的对象 (tng)—?tng)全都通过 (tng)RMI-IIOP。?br />
Server.java (tng)的?tng)main (tng)Ҏ(gu)初始化一个?tng)ORB。这个?tng)ORB (tng)设|ؓ(f) (tng)8080 (tng)的?tng)com.ibm.CORBA.ListenerPort (tng)属性作为参C入。这得?tng)ORB (tng)在端口?080 (tng)上侦听传入请求。请注意Q?tng)com.ibm.CORBA.ListenerPort (tng)是一个专有的 (tng)I(yng)BM (tng)属性。如果?zhn)惛_另一供应商的 (tng)ORB (tng)上运行这些代码,那?zhn)应该参阅该供应商的文档,扑ֈ适当的属性。(Sun (tng)使用 (tng)com.sun.CORBA.POA.ORBPersistentServerPort (tng)Q但它只在?zhn)使用?tng)POAQportable (tng)object (tng)adapterQ可UL对象适配器)(j)伺服器(servantQ时才能够工作。)(j) (tng)
初始化?tng)ORB (tng)后,main (tng)Ҏ(gu)接着对?tng)Server (tng)对象q行实例化。因个?tng)server (tng)对象也是一个?tng)PortableRemoteObject (tng)Q所以缺省构造函C(x)自动调用 (tng)exportObject(this) (tng)。这个对象现在已l就l于接收q程调用。?br />
接着Q我们需要通过调用 (tng)ORB.register_initial_reference(String,orb.omg.CORBA.Object) (tng)注册q个对象。ؓ(f)此,我们需要把我们的?tng)server (tng)对象作ؓ(f) (tng)org.omg.CORBA.Object (tng)的引用。调用?tng)PortableRemoteObject.toStub(s) (tng)实现?jin)这一点,因ؓ(f)所q回的对象都实现?jin) (tng)java.rmi.Remote (tng)和?tng)org.omg.CORBA.Object (tng)。?br />
然后Q返回的 (tng)org.omg.CORBA.Object (tng)对象向服务器端?tng)ORB (tng)注册为“OurLittleClient”。ؓ(f)?jin)确保 (tng)I(yng)NS (tng)h能够定位对象Q我们用注册调用?tng)register_initial_reference (tng)。当 (tng)I(yng)NS (tng)调用q入 (tng)ORB (tng)ӞORB (tng)查扑ַl以正在被请求的名称注册的对象。由于我们将对象注册为“OurLittleClient”,所以,当一个?tng)I(yng)NS (tng)调用q入我们的服务器 (tng)ORB (tng)要求“OurLittleClient”时Q我们将知道客户机正在查扄是哪个对象。?br />
最后,我确信?zhn)已经注意到我们将?tng)ORB (tng)强制转型成?tng)com.ibm.CORBA.iiop.ORB (tng)。因为?tng)Sun (tng)未公开 (tng)org.omg.CORBA.ORB (tng)接口的?tng)register_initial_reference (tng)Q所以?tng)I(yng)BM (tng)SDK (tng)也不能将它公开。因此,我们必须我们的 (tng)ORB (tng)强制转型成?tng)I(yng)BM (tng)ORB。随着 (tng)Sun (tng)来遵循?tng)OMGQJDK (tng)的未来版本(1.4.0 (tng)后)(j)可能不需要这U强制{型。?br />
是q样Q?tng)很单吧—?tng)嗯Q是有点。我们的服务器现在正在等待传入客h (tng)I(yng)NS (tng)h。但客户机怎么样呢Q?br />
W? (tng)部分Q构建客h
客户机应用程序的代码如清单? (tng)所C:(x)
清单 (tng)4. (tng)Client.java
/*
(tng)* (tng)Client (tng)application
(tng)*/
import (tng)javax.rmi.PortableRemoteObject;
import (tng)org.omg.CORBA.ORB;
public (tng)class (tng)Client (tng){
(tng) (tng)public (tng)static (tng)void (tng)main(String[] (tng)args) (tng){
(tng) (tng) (tng) (tng)try (tng){
(tng) (tng) (tng) (tng) (tng) (tng)ORB (tng)orb (tng)= (tng)ORB.init(args, (tng)null);
(tng) (tng) (tng) (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)// (tng)here's (tng)the (tng)URL (tng)for (tng)the (tng)local (tng)host
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)String (tng)I(yng)NSUrl (tng)= (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)"corbaloc:iiop:1.2@localhost:8080/OurLittleClient"; (tng) (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)// (tng)get (tng)the (tng)reference (tng)to (tng)the (tng)remote (tng)process
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)org.omg.CORBA.Object (tng)objRef=orb.string_to_object(INSUrl);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)// (tng)narrow (tng)it (tng)into (tng)our (tng)RMIInterface
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)RMIInterface (tng)ri (tng)= (tng)
(tng) (tng)(RMIInterface)PortableRemoteObject.narrow(objRef, (tng)RMIInterface.class);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)
(tng) (tng) (tng) (tng) (tng) (tng)// (tng)call (tng)the (tng)hello (tng)method
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)System.out.println("received (tng)from (tng)server: (tng)"+ri.hello()+"\n"); (tng) (tng)
(tng) (tng) (tng) (tng)
(tng) (tng) (tng) (tng) (tng) (tng)// (tng)try (tng)RMI (tng)serialization
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)SerClass (tng)se (tng)= (tng)new (tng)SerClass(5, (tng)"Client (tng)string! (tng)");
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)// (tng)pass (tng)the (tng)class (tng)to (tng)be (tng)altered (tng)on (tng)the (tng)server
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)// (tng)of (tng)course (tng)behind (tng)the (tng)scenes (tng)this (tng)class (tng)is (tng)being (tng)
(tng) (tng) (tng) (tng) (tng) (tng)// (tng)serialized (tng)over (tng)I(yng)IOP
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)se (tng)= (tng)ri.alterClass(se);
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)// (tng)now (tng)let's (tng)see (tng)the (tng)result
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)System.out.println("Serialization (tng)results (tng):\n"+
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)"Integer (tng)was (tng)5 (tng)now (tng)is (tng)"+se.getX()+"\n"+
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)"String (tng)was (tng)\"Client (tng)String! (tng)\" (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)now (tng)is (tng)\""+se.getString()+"\""); (tng) (tng) (tng)
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)} (tng)catch (tng)(Exception (tng)e) (tng){
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)e.printStackTrace();
(tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)}
(tng) (tng) (tng) (tng)}
}
(tng)
如何分解客户Z?br />
客户Z码比服务器代码要单一些。我们初始化一个?tng)ORBQ然后调用?tng)string_to_object(String) (tng)Q其中的 (tng)string (tng)是我们的 (tng)I(yng)NS (tng)URL。构造?tng)I(yng)NS (tng)URL (tng)相当单:(x)首先Q我们指定我们用?tng)corbaloc (tng)URLQ请参阅 (tng)参考资料)(j)和?tng)I(yng)IOP (tng)协议版本 (tng)1.2。接着Q我们将L名(www.whatever.comQ和要连接的端口dq去。最后,我们指定我们要查扄服务的名U。结果?tng)I(yng)NS (tng)URL (tng)是?tng)corbaloc:iiop:1.2@localhost:8080/OurLittleClient。?br />
当我们将q个 (tng)URL (tng)传递到 (tng)ORB.string_to_object(String) (tng)ӞORB (tng)分z一个请求到所指定的服务器Q以h所h的服务。假设一切运转正常,则?tng)ORB (tng)接收回该服务的一个对象引用(实际上是一个?tng)I(yng)ORQ。然后,我们该对象引用强制转型QnarrowQ成我们能够使用的东西,ꐠRMIInterface (tng)Q这P我们׃ؓ(f)开始调用方法做好了(jin)准备。?br />
在调用了(jin)单的 (tng)hello (tng)Ҏ(gu)Q它应该不需要Q何解释吧Q之后,我们可以开始探讨?tng)RMI-IIOP (tng)的序列化功能?jin)。首先,我们创徏一个?tng)SerClass (tng)Q一个可序列化的 (tng)Java (tng)c,q初始化它的成员变量。接着Q我们将q个cM入到我们的方法,Ҏ(gu)通过 (tng)I(yng)IOP (tng)类写出到服务器。服务器dcdƈ它重创Zؓ(f)服务器端 (tng)Java (tng)对象Q修改它的成员|然后q回它(使用 (tng)I(yng)IOPQ作为方法的q回倹{当接收到在q程Ҏ(gu)调用之后重创建的对象Ӟ我们看到它的成员实已被服务器修改了(jin)。就是这么简单:(x)在?tng)I(yng)IOP (tng)上进行?tng)Java (tng)序列化。?br />
(tng)
W? (tng)部分Q运行示?br />
h意,我们q里所创徏的示例必d (tng)I(yng)BM (tng)Developer (tng)Kit (tng)for (tng)Java (tng)technologyQ版本?.3.1 (tng)或更高版本中q行。如果?zhn)宁愿使用?tng)Sun (tng)JDKQ请下蝲 (tng)特定于?tng)Sun (tng)的源代码Q?zhn)应该在 (tng)Sun (tng)1.4.0 (tng)JDK (tng)或更高版本中q行它。这个源代码包括一个解释?tng)I(yng)BM (tng)SDK (tng)版本和?tng)Sun (tng)JDK (tng)版本之间的差异的 (tng)readme.txt (tng)文g。如果?zhn)没有?tng)I(yng)BM (tng)Developer (tng)Kit (tng)for (tng)Java (tng)technologyQ而?zhn)又想要一个)(j)Q请 (tng)现在׃载一个;它们是免费的。?br />
q里是运行示例的步骤Q?br />
下蝲 (tng)源文件。?br />
输入 (tng)javac (tng)*.java (tng)Qjavac (tng)所有文件。?br />
对?tng)server (tng)c运行?tng)rmic (tng)Q带 (tng)I(yng)IOP (tng)标志Q:(x) (tng)rmic (tng)-iiop (tng)Server (tng)。?br />
启动服务器:(x)在?tng)Windows (tng)中,误入?tng)start (tng)java (tng)Server (tng)。?br />
启动客户机:(x)在?tng)Windows (tng)中,误入?tng)start (tng)java (tng)Client (tng)?br /> (tng)
关于 (tng)RMI-IIOP (tng)和?tng)EJB (tng)lg的一Ҏ(gu)?br />
EJB (tng)2.0 (tng)规范指出QEJB (tng)lg必须能在 (tng)RMI (tng)和?tng)RMI-IIOP (tng)上运行。添加?tng)RMI-IIOP (tng)作ؓ(f)针对 (tng)EJB (tng)lg的在U协议,已经l将 (tng)J2EE (tng)环境集成到现有的企业基础设施Q多数是 (tng)CORBA (tng)相当密集的)(j)带来?jin)很大帮助。但它也引v?jin)一些问题?br />
单地_(d)是定制构建的lg和?tng)EJB (tng)lg集成h要求(zhn)(开发者)(j)处理道QplumbingQ,否则在?tng)EJB (tng)体系l构中它们对(zhn)来说将很抽象。到目前为止Q还没有解决q个问题的简单方案,可能永远也不?x)有。随着诸如 (tng)Web (tng)服务q样的技术的发展Q或怼(x)出现解决Ҏ(gu)Q但目前未可知?br />
(tng)
l束语:(x)此后该做什?br />
我希望本文已l向(zhn)展CZ(jin)构徏和运行?tng)RMI-IIOP (tng)客户机/服务器应用程序是多么Ҏ(gu)。?zhn)可以修改一下我们用的CZQ用U?tng)CORBA (tng)替代客户机或服务器,不过q样做将除去(zhn)应用程序中的?tng)Java (tng)序列化?br />
如果(zhn)想在?tng)CORBA (tng)环境中用?tng)RMI-IIOPQ那么看看?tng)I(yng)DL (tng)如何映射成?tng)Java (tng)以及(qing) (tng)Java (tng)如何映射成?tng)I(yng)DL (tng)是值得的。如果?zhn)惛_不安全的环境Q即不是(zhn)自q (tng)PCQ中部v (tng)RMI-IIOPQ那么研I一下?tng)CORBA (tng)安全功能Q如拦截器和 (tng)CORBA (tng)安全模型Q以?qing)其它 (tng)CORBA (tng)企业功能Q如事务处理Q是个不错的L。CORBA (tng)所有的丰富功能在?zhn)q行 (tng)RMI-IIOP (tng)旉可以使用?br />
(zhn)可以随意提出对本文的意见?tng)—?tng)或者直接提l?tng)我Q或者提刊W讨坛。我Ҏ(gu)的想法很感兴。?br />
(tng)
(tng)
参考资料?br />
(zhn)可以参阅本文在 (tng)developerWorks (tng)全球站点上的 (tng)英文原文. (tng)
请单?yn)L文顶部或底部的?tng)讨论参加本文的?tng)讨论论坛。?br />
下蝲 (tng)本文与?tng)I(yng)BM (tng)兼容的源代码。?br />
下蝲 (tng)本文与?tng)Sun (tng)兼容的源代码。?br />
IIOP (tng)协议是由 (tng)对象理l织QObject (tng)Management (tng)GroupQOMGQ)(j)制定的,q个l织q制定ƈl护着 (tng)CORBA (tng)规范。?br />
要更多了(jin)解?tng)CORBAQ请讉K (tng)OMG (tng)的?tng)CORBA (tng)Web (tng)站点。?br />
要更多了(jin)解?tng)RMIQ请讉K (tng)RMI (tng)主页。?br />
“The (tng)Java (tng)Developer (tng)Connection”提供了(jin)一?tng)I(yng)NS (tng)教程Q它也对命名服务、CosNaming (tng)服务和?tng)corbaloc (tng)URL (tng)格式做了(jin)一般介l。?br />
x(chng)索一下?zhn)有哪些 (tng)Java (tng)技术选择吗?请参阅?tng)I(yng)BM (tng)Developer (tng)Kit (tng)for (tng)Java (tng)technology的完整清单。?br />
要更多了(jin)解?tng)I(yng)BM (tng)Developer (tng)Kit (tng)for (tng)Java (tng)technologyQ版本?.3 (tng)和?tng)RMI-IIOPQ请参阅 (tng)javax.rmi.CORBA (tng)cdơ结构。?br />
要获得对用?tng)RMI (tng)和?tng)CORBA (tng)~程的更q一步介l,请学?fn)教E“?tng)RMI, (tng)CORBA, (tng)and (tng)Distributed (tng)Objects”( (tng)developerWorksQ?000 (tng)qb?0 (tng)月)(j)。?br />
如果(zhn)是用?tng)EJB (tng)lg~程的新手,(zhn)可能需要学?fn)教E“?tng)EnterpriseJavaBeans (tng)fundamentals”( (tng)developerWorksQ?001 (tng)qb? (tng)月)(j)。?br />
要更多了(jin)解?tng)EJB (tng)技术和 (tng)CORBA (tng)之间的关p,请参阅?tng)Ken (tng)Nordby (tng)的“?tng)Deployingand (tng)using (tng)Enterprise (tng)JavaBeans (tng)components”—?tng)对?tng)EJB (tng)技术的分ؓ(f)三个部分的介l的W? (tng)部分Q?tng)developerWorksQ?000 (tng)qb? (tng)月)(j)。?br />
RMI-IIOP (tng)的主要设计师在?tng)JavaWorld上的文章“?tng)RMIover (tng)I(yng)IOP”讲qC(jin)他对此项技术的看法Q?tng)JavaWorldQ?999 (tng)qb?2 (tng)月)(j)。?br />
要全方位?jin)解?tng)RMI-IIOPQ请参阅 (tng)theServerSide.com (tng)上的文章“?tng)RMI/IIOP, (tng)nice (tng)idea (tng)but (tng)the (tng)reality (tng)is (tng)turning (tng)out (tng)to (tng)be (tng)different”,它着重讲qWRMI-IIOP (tng)不提供的东西QTheServerside.comQ。?br />
关于作?br /> (tng)Damian (tng)Hagge (tng)在?tng)I(yng)BM (tng)的?tng)Hursley (tng)开发实验室工作。虽然他目前住在英国Q但他的出生地比他目前的居住地晚五个时区Q四十九(ji)U度U偏上一点(寚w些地理不达标的hQ就是加拿大Q。除?jin)作为开发者在 (tng)I(yng)BM (tng)Java (tng)ORB (tng)组工作和写一些关于不易理解的主题的长大Z外,Damian (tng)q是一个知晓各U鸡毛蒜皮小事的人;比如_(d)(zhn)知道冰岛支持自立的不断发展的香蕉业吗QDamian (tng)q做一些常规运动,例如NQpower (tng)liftingQ(如果(zhn)认ZD重是常规q动的话Q)(j)。?zhn)可以通过 (tng)Hagge@uk.ibm.com与他联系?img src ="http://www.aygfsteel.com/liujw/aggbug/39151.html" width = "1" height = "1" />
]]>
վ֩ģ壺
|
Ľ|
ֹ|
Ԫ|
Ǧɽ|
Ž|
|
ƽ|
ζ|
ľ|
|
|
¤|
|
|
ʯ|
|
|
|
|
ľ|
|
۲|
пǰ|
ƽ|
ƽ|
|
Ϫ|
|
|
ĵ|
|
|
|
|
ױ|
|
ԣ|
|
ӯ|
ʯ|