友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
Java编程思想第4版[中文版](PDF格式)-第156部分
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!
码,并可发出远程调用。我们将这种代码称为“根干”(Stub and Skeleton)代码,它组织成多个Java 源
文件,而且通常属于同一个Java 包的一部分。
2。 命名服务
命名服务属于CORBA 基本服务之一。CORBA 对象是通过一个引用访问的。尽管引用信息用我们的眼睛来看没
什么意义,但可为引用分配由程序员定义的字串名。这一操作叫作“引用的字串化”。一个叫作“命名服
务”(Naming Service)的OMA 组件专门用于执行“字串到对象”以及“对象到字串”转换及映射。由于命
名服务扮演了服务器和客户都能查询和操作的一个电话本的角色,所以它作为一个独立的进程运行。创建
“对象到字串”映射的过程叫作“绑定一个对象”;删除映射关系的过程叫作“取消绑定”;而让对象引用
传递一个字串的过程叫作“解析名称”。
比如在启动的时候,服务器应用可创建一个服务器对象,将对象同命名服务绑定起来,然后等候客户发出请
求。客户首先获得一个服务器引用,解析出字串名,然后通过引用发出对服务器的调用。
同样地,“命名服务”规范也属于CORBA 的一部分,但实现它的应用程序是由ORB 厂商(开发商)提供的。
由于厂商不同,我们访问命名服务的方式也可能有所区别。
A。6。2 一个例子
这儿显示的代码可能并不详尽,因为不同的ORB 有不同的方法来访问CORBA 服务,所以无论什么例子都要取
决于具体的厂商(下例使用了JavaIDL,这是 Sun 公司的一个免费产品。它配套提供了一个简化版本的ORB、
一个命名服务以及一个“IDL→Java ”编译器)。除此之外,由于 Java 仍处在发展初期,所以在不同的
Java/CORBA 产品里并不是包含了所有 CORBA 特性。
我们希望实现一个服务器,令其在一些机器上运行,其他机器能向它查询正确的时间。我们也希望实现一个
客户,令其请求正确的时间。在这种情况下,我们让两个程序都用Java 实现。但在实际应用中,往往分别采
用不同的语言。
1。 编写 IDL源码
667
…………………………………………………………Page 669……………………………………………………………
第一步是为提供的服务编写一个 IDL描述。这通常是由服务器程序员完成的。随后,程序员就可用任何语言
实现服务器,只需那种语言里存在着一个CORBA IDL 编译器。
IDL文件已分发给客户端的程序员,并成为两种语言间的桥梁。
下面这个例子展示了时间服务器的 IDL描述情况:
module RemoteTime {
interface ExactTime {
string getTime();
};
};
这是对 RemoteTime 命名空间内的 ExactTime 接口的一个声明。该接口由单独一个方法构成,它以字串格式返
回当前时间。
2。 创建根干
第二步是编译 IDL,创建Java 根干代码。我们将利用这些代码实现客户和服务器。与JavaIDL 产品配套提供
的工具是idltojava:
idltojava …fserver …fclient RemoteTime。idl
其中两个标记告诉 idltojava 同时为根和干生成代码。idltojava 会生成一个 Java 包,它在 IDL模块、
RemoteTime 以及生成的Java 文件置入 RemoteTime 子目录后命名。_ExactTimeImplBase。java 代表我们用于
实现服务器对象的“干”;而_ExactTimeStub。java 将用于客户。在ExactTime。java 中,用Java 方式表示
了IDL 接口。此外还包含了用到的其他支持文件,例如用于简化访问命名服务的文件。
3。 实现服务器和客户
大家在下面看到的是服务器端使用的代码。服务器对象是在ExactTimeServer 类里实现的。
RemoteTimeServer 这个应用的作用是:创建一个服务器对象,通过 ORB 为其注册,指定对象引用时采用的名
称,然后“安静”地等候客户发出请求。
import RemoteTime。*;
import org。omg。CosNaming。*;
import org。omg。CosNaming。NamingContextPackage。*;
import org。omg。CORBA。*;
import java。util。*;
import java。text。*;
// Server object implementation
class ExactTimeServer extends _ExactTimeImplBase{
public String getTime(){
return DateFormat。
getTimeInstance(DateFormat。FULL)。
format(new Date(
System。currentTimeMillis()));
}
}
// Remote application implementation
public class RemoteTimeServer {
public static void main(String args'') {
try {
// ORB creation and initialization:
668
…………………………………………………………Page 670……………………………………………………………
ORB orb = ORB。init(args; null);
// Create the server object and register it:
ExactTimeServer timeServerObjRef =
new ExactTimeServer();
orb。connect(timeServerObjRef);
// Get the root naming context:
org。omg。CORBA。Object objRef =
orb。resolve_initial_references(
〃NameService〃);
NamingContext ncRef =
NamingContextHelper。narrow(objRef);
// Assign a string name to the
// object reference (binding):
Nameponent nc =
new Nameponent(〃ExactTime〃; 〃〃);
Nameponent path'' = {nc};
ncRef。rebind(path; timeServerObjRef);
// Wait for client requests:
java。lang。Object sync =
new java。lang。Object();
synchronized(sync){
sync。wait();
}
}
catch (Exception e) {
System。out。println(
〃Remote Time server error: 〃 + e);
e。printStackTrace(System。out);
}
}
}
正如大家看到的那样,服务器对象的实现是非常简单的;它是一个普通的 Java 类,从 IDL 编译器生成的
“干”代码中继承而来。但在与ORB 以及其他CORBA 服务进行联系的时候,情况却变得稍微有些复杂。
4。 一些CORBA 服务
这里要简单介绍一下JavaIDL 相关代码所做的工作(注意暂时忽略了CORBA 代码与不同厂商有关这一事
实)。main()的第一行代码用于启动 ORB。而且理所当然,这正是服务器对象需要同它进行沟通的原因。就
在ORB 初始化以后,紧接着就创建了一个服务器对象。实际上,它正式名称应该是“短期服务对象”:从客
户那里接收请求,“生存时间”与创建它的进程是相同的。创建好短期服务对象后,就会通过ORB 对其进行
注册。这意味着ORB 已知道它的存在,可将请求转发给它。
到目前为止,我们拥有的全部东西就是一个timeServerObjRef——只有在当前服务器进程里才有效的一个对
象引用。下一步是为这个服务对象分配一个字串形式的名字。客户会根据那个名字寻找服务对象。我们通过
命名服务(Naming Service)完成这一操作。首先,我们需要对命名服务的一个对象引用。通过调用
resolve_initial_references(),可获得对命名服务的字串式对象引用(在JavaIDL 中是
“NameService”),并将这个引用返回。这是对采用narrow()方法的一个特定NamingContext 引用的模
型。我们现在可开始使用命名服务了。
为了将服务对象同一个字串形式的对象引用绑定在一起,我们首先创建一个Nameponent 对象,用
“ExactTime”进行初始化。“ExactTime”是我们想用于绑定服务对象的名称字串。随后使用rebind()方
法,这是受限于对象引用的字串化引用。我们用rebind()分配一个引用——即使它已经存在。而假若引用已
经存在,那么bind()会造成一个异常。在CORBA 中,名称由一系列NameContext 构成——这便是我们为什么
要用一个数组将名称与对象引用绑定起来的原因。
669
…………………………………………………………Page 671……………………………………………………………
服务对象最好准备好由客户使用。此时,服务器进程会进入一种等候状态。同样地,由于它是一种“短期服
务”,所以生存时间要受服务器进程的限制。JavaIDL 目前尚未提供对“持久对象”(只要创建它们的进程
保持运行状态,对象就会一直存在下去)的支持。
现在,我们已对服务器代码的工作有了一定的认识。接下来看看客户代码:
import RemoteTime。*;
import org。omg。CosNaming。*;
import org。omg。CORBA。*;
public class RemoteTimeClient {
public static void main(String args'') {
try {
// ORB creation and initialization:
ORB orb = ORB。init(args; null);
// Get the root naming context:
org。omg。CORBA。Object objRef =
orb。resolve_initial_references(
〃NameService〃);
NamingContext ncRef =
NamingContextHelper。narrow(objRef);
// Get (resolve) the stringified object
// reference for the time server:
Nameponent nc =
new Nameponent(〃ExactTime〃; 〃〃);
Nameponent path'' = {nc};
ExactTime timeObjRef =
ExactTimeHelper。narrow(
ncRef。resolve(path));
// Make requests to the server object:
String exactTime = timeObjRef。getTime();
System。out。println(exactTime);
} catch (Exception e) {
System。out。println(
〃Remote Time server error: 〃 + e);
e。printStackTrace(System。out);
}
}
}
前几行所做的工作与它们在服务器进程里是一样的:ORB 获得初始化,并解析出对命名服务的一个引用。
接下来,我们需要用到服务对象的一个对象引用,所以将字串形式的对象引用直接传递给resolve()方法,
并用narrow()方法将结果造型到 ExactTime 接口引用里。最后调用 getTime()。
5。 激活名称服务进程
现在,我们已分别获得了一个服务器和一个客户应用,它们已作好相互间进行沟通的准备。大家知道两者都
需要利用命名服务绑定和解析字串形式的对象引用。在运行服务或者客户之前,我们必须启动命名服务进
程。在JavaIDL 中,命名服务属于一个 Java 应用,是随产品配套提供的。但它可能与其他产品有所不同。
JavaIDL 命名服务在 JVM 的一个实例里运行,并(默认)监视网络端口 900。
6。 激活服务器与客户
现在,我们已准备好启动服务器和客户应用(之所以按这一顺序,是由于服务器的存在是“短期”的)。若
各个方面都设置无误,那么获得的就是在客户控制台窗口内的一行输出文字,提醒我们当前的时间是多少。
670
…………………………………………………………Page 672……………………………………………………………
当然,这一结果本身并没有什么令人兴奋的。但应注意一个问题:即使都处在同一台机器上,客户和服务器
应用仍然运行于不同的虚拟机内。它们之间的通信是通过一个基本的集成层进行的——即ORB 与命名服务的
集成。
这只是一个简单的例子,面向非网络环境设计。但通常将 ORB 配置成“与位置无关”。若服务器与客户分别
位于不同的机器上,那么ORB 可用一个名为“安装库”(Implementation Repository)的组件解析出远程字
串式引用。尽管“安装库”属于CORBA 的一部分,但它几乎没有具体的规格,所以各厂商的实现方式是不尽
相同的。
正如大家看到的那样,CORBA 还有许多方面的问题未在这儿进行详细讲述。但通过以上的介绍,应已对其有
一个基本的认识。若想获得 CORBA 更详细的资料,最传真的起点莫过于OMB Web 站点,地址是
http://omg。org 。这个地方提供了丰富的文档资料、白页、程序以及对其他CORBA 资源和产品的链接。
A。6。3 Java 程序片和 CORBA
Java 程序片可扮演一名 CORBA 客户的角色。这样一来,程序片就可访问由CORBA 对象揭示的远程信息和服
务。但程序片只能同最初下载它的那个服务器连接,所以程序片与它沟通的所有 CORBA 对象都必须位于那台
服务器上。这与CORBA 的宗旨是相悖的:它许诺可以实现“位置的透明”,或者“与位置无关”。
将Java 程序片作为 CORBA 客户使用时,也会带来一些安全方面的问题。如果您在内联网中,一个办法是放宽
对浏览器的安全限制。或者设置一道防火墙,以便建立与外部服务器安全连接。
针对这一问题,有些Java ORB 产品专门提供了自己的解决方案。例如,有些产品实现了一种名为“HTTP 通
道”(HTTP Tunneling)的技术,另一些则提供了特别的防火墙功能。
作为放到附录中的内容,所有这些主题都显得太复杂了。但它们确实是需要重点注意的问题。
A。6。4 比较 CORBA 与 RMI
我们已经知道,CORBA 的一项主要特性就是对 RPC (远程过程调用)的支持。利用这一技术,我们的本地对象
可调用位置远程对象内的方法。当然,目前已有一项固有的Java 特性可以做完全相同的事情:RMI (参考第
15章)。尽管 RMI 使 Java 对象之间进行RPC 调用成为可能,但 CORBA 能在用任何语言编制的对象之
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!