服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

用分布式对象技术构造java应用


  用java,rmi 和horb 实 现 分 布 式 对 象 环 境

--------------------------------------------------------------------------------

摘 要 本 文 原 发 表 在 十 二 月 的 日 文javaworld 印 刷 版 上, 概 括 地 介 绍 了 分 布 式 对 象 技 术, 重 点 介 绍 了 其 中 的 两 种 具 体 技 术: 远 程 方 法 启 用(rmi) 和hirano 对 象 请 求 代 理(horb)。 通 过 代 码 实 例 和 图 解, 你 自 己 便 能 判 定 哪 种 分 布 式 对 象 技 术 最 适 合 你。

直 到 最 近, 软 件 程 序 用 面 向 对 象 设 计 方 法 创 建 时, 设 计 主 要 运 行 在 单 机 的 内 存 里。 为 了 使 软 件 适 应 网 络 运 用 和 保 存 在 二 级 存 贮 里, 除 了 面 向 对 象 方 法 以 外, 还 需 要 其 他 的 设 计 方 法。 人 们 开 发 了 面 向 网 络 的 分 布 式 对 象 技 术 来 解 决 这 个 问 题。 同 时, 可 以 将 对 象 直 接 存 贮 在 二 级 存 贮 里 的 面 向 对 象 数 据 库(odbms) 技 术 诞 生 了。

这 些 技 术 都 不 是 新 的,-- 支 持odbms 的 开 发 工 具 在90 年 代 早 期 便 出 现 在 市 场 上, 然 而 这 些 产 品 不 是 价 格 太 高, 使 用 无 名 的 语 言, 就 是 没 有 获 得 工 程 师 行 业 的 广 泛 认 可。 随 着java 的 出 现, 分 布 式 对 象 技 术 和odbms 技 术 得 到 了 进 一 步 的 发 展, 而 且 价 格 下 降 了, 所 以 获 得 了 工 程 师 们 的 接 受。 根 据 最 近 软 件 的 动 向, 这 些 技 术 得 到 越 来 越 广 泛 的 关 注。

很 明 显, 未 来 的 软 件 环 境 必 须 包 括 三 项 重 要 的 技 术:

1. “ 面 向 对 象”

2. “ 网 络”

3. “ 数 据 库”

这 些 环 境 可 以 用 分 布 式 对 象 技 术 和odbms 来 实 现。 本 文 的 中 心 是 基 于java 的 分 布 式 对 象 技 术。

什 么 是 分 布 式 对 象
简 单 说 来, 分 布 式 对 象 技 术 允 许 在 不 同 机 器 上 的 对 象 相 互 传 递 消 息(java 方 法 调 用)。 为 了 便 于 理 解 什 么 是 分 布 式 对 象, 请 看 图1, 一 个 网 络 卡 拉ok 模 型 的 设 计。 正 如 你 看 到 的, 当 一 个 远 程 操 作 在 服 务 器 中 的karaoke box 执 行 歌 曲 选 择 时, 一 个music 对 象 将 被 送 到 客 户 机。 客 户 机 通 过 发 送“ 播 放” 消 息 启 动 音 乐。 以 下 定 义 一 些 术 语: 等 同 于karaoke box 的 对 象 称 为“ 远 程 对 象”, 发 送 给 客 户 机 的music 对 象 称 为“ 拷 贝 对 象”, 由 客 户 机 发 往 服 务 器 上 的karaoke box 对 象 的 消 息 称 为“ 远 程 消 息”, 我 们 将 用 这 个 模 型 实 现 一 个 分 布 式 对 象 系 统。

图1: 网 络 卡 拉ok 模 型 图

rmi 和horb 概 述
本 文 的 中 心 是 两 项 分 布 式 对 象 技 术:rmi( 远 程 方 法 启 用), 它 捆 绑 于jdk1.1 的 标 准 特 征 中, 和horb(hirano 对 象 请 求 代 理), 它 由 美 国 国 家 电 子 研 究 所( 国 际 贸 易 和 工 业 部) 的satoshi hirano 开 发。 本 文 的 最 后 将 介 绍corba, 它 致 力 于 成 为 工 业 标 准 的 分 布 式 对 象 系 统。 关 于horb 的 最 新 信 息, 可 在 以 下url 中 查 到:http://ring .tel.go.jp/openlab/horb/。

分 布 式 对 象 的 应 用(horb 与rmi)
我 试 图 用 这 两 项 技 术, horb 和rmi 来 构 造 一 个 分 布 式 对 象 系 统。 理 解 这 些 技 术 最 快 的 方 法 是 通 过 获 得 实 际 的 动 手 经 验。

首 先, 我 们 将 基 于 网 络 卡 拉ok 模 型 设 计 类。 图2 为 一 个 类 示 图, 它 说 明 了 基 于 内 部 类 结 构 和 类 创 建 的 实 例 之 间 的 关 系 结 构。

图2: 网 络 卡 拉ok 模 型 的 类 示 图

horb 介 绍
这 部 分 提 供 一 个 如 何 使 用horb 的 例 子。 与rmi 相 比,horb 允 许 以 类 似 于 常 规 面 向 对 象 编 程 的 格 式 编 码, 列 表1 是horb 卡 拉ok 类 的 源 代 码(karaoke.java)

列 表1:karaoke box 类[horb]

class karaokebox{
void hello(string s){
system.out.println("client name " + s);
}
}

列 表2 是 使 用karaoke box 的 客 户 机 的 源 代 码(client.java)。 首 先 调 用karaokebox 类 的hello() 方 法。 到 此, 程 序 不 是 分 布 式 对 象。 对karaokebox 类 的hello() 方 法 的 调 用 也 是 本 地 调 用。

列 表2: 使 用karaoke box 的 客 户 机 的 源 代 码[horb]

class client{
public static void main(string argv[]){
string name = (argv.length == 1) ? argv[0] : "-";
karaokebox box = new karaokebox();
box.hello(name);
}
}

现 在 我 们 将 用 一 个 小 魔 术 将karaokebox 转 换 成 远 程 对 象。 首 先 对 客 户 机 源 代 码 做 修 改。 如 列 表3 所 示。 这 将 告 诉 你 在 远 程 操 作 中 如 何 使 用karaokebox(client.java)。 由 列 表2 中 修 改 的 部 分 用 注 释 标 注。 在 列 表3 中, 创 建 了karaokebox_proxy 的 实 例, 而 不 是karaokebox。 那 么 什 么 时 候 创 建 最 重 要 的karaokebox 实 例 ? 答 案 是 在 创 建karaokebox_proxy 实 例 时。

列 表3: 在 远 程 操 作 中 使 用karaokebox(client.java)[horb]

import horb.orb.*; // add

class client{
public static void main(string argv[]){
string name = (argv.length == 1) ? argv[0] : "-";
karaokebox_proxy box = new karaokebox_proxy("horb://kinta"); // change (change host name)
box.hello(name);
}
}

在 下 面 的 代 码 例 子 中, 你 将 看 到 在rmi 操 作 中 如 何 使 用karaokebox(client.java)

列 表4: 在rmi 操 作 中 使 用karaokebox(client.java)[rmi]

class client{
public static void main(string argv[]){
string name = (argv.length == 1) ? argv[0] : "-";
try{ //change
karaokebox box = (karaokebox)java.rmi.naming.lookup("rmi://kinta/karaokebox1");//change
box.hello(name);
} //change
catch(exception e){e.printstacktrace();} //change
}
}

图3 显 示 了karaoke box 的 机 制。

图3:karaoke box 的 远 程 操 作 机 制[horb]

karaokebox_proxy 称 为karaokebox 的“ 代 理 对 象”。 karaokebox 的 实 际 实 例 位 于 服 务 器 上( 本 例 中 的 主 机 名 为“kinta”)。 客 户 机 创 建karaokebox_proxy 的 实 例 作 为 代 理 对 象。 发 送 给karaokebox 的 消 息 先 发 给karaokebox_proxy, 消 息 通 过karaokebox_proxy 和 被 称 为karaoke_skeleton 的 机 制 转 发 给karaokebox 实 例,karaoke_skeleton 位 于 服 务 器 上, 结 果 返 回 到 客 户 机。 所 以 远 程 对 象 操 作 才 成 为 可 能。

这 是 必 要 的 源 代 码 修 改。horb 一 个 很 好 特 点 是 远 程 对 象karaokebox 的 源 代 码 根 本 不 用 修 改。

创 建 运 行 环 境
horb 编 译 器 会 自 动 创 建karaokebox_proxy 和karaoke_skeleton。 与 往 常 一 样,client.java 用java 编 程 器 编 译。

1.> horbc karaokebox.java 创 建

karaokebox.class

karaokebox_proxy.class

karaokebox_skeleton.class
2.> javac client.java 创 建

client.class.
3. 将client.class 和karaokebox_proxy.class 拷 贝 到 客 户 机, 将karaokebox.class 和karaokebox_skeleton.class 拷 贝 到 服 务 器(horb 必 须 安 装 在 客 户 机 和 服 务 器 上)。

运 行 过 程

1. 在 服 务 器 上 启 动horb 精 灵。

2. 在 客 户 机 上 以 字 符 串“junzo” 作 为 参 数 启 动client.

3. 结 果"client name junzo" 显 示 在 服 务 器 上。

运 行 结 果 如 图4 所 示

图4 :horb 运 行 结 果

rmi 介 绍
本 部 分 介 绍 如 何 使 用rmi。 首 先, 修 改 客 户 机 的 源 代 码, 如 列 表4 所 示。 修 改 的 位 置 几 乎 与horb 的 修 改 一 样。 从 列 表2 的 修 改 用 注 释 标 注。

在 列 表4 中, 使 用 了 称 为lookup() 的rmi 方 法 代 替 调 用new 创 建karaokebox 的 实 例。lookup() 创 建karaokebox 实 例 吗 ? 实 际 上, 不。 其 中 原 因 以 后 解 释。

使 用rmi,karaokebox 源 代 码 也 要 修 改。 首 先 要 创 建java 接 口。 列 表5 是karaokebox 接 口 的 源 代 码(karaokebox.java)。 客 户 机 从lookup() 接 收 到 的 对 象 类 型 就 是 此 接 口。

列 表5:karaoke box 接 口(karaokebox.java)[rmi]

interface karaokebox extends java.rmi.remote{

public void hello(string s) throws java.rmi.remoteexception;

}

列 表6 是 实 现 接 口 的 类 的 源 代 码(karaokeboximpl.java)。 与 最 初 的 非 分 布 式 对 象 源 代 码 相 比( 列 表1), 它 具 有 更 多 的 代 码。

列 表6:karaoke box 实 现(karaokeboximpl.java)[rmi]

import java.rmi.*;
import java.rmi.server.unicastremoteobject;

public class karaokeboximpl extends unicastremoteobject implements karaokebox{
public karaokeboximpl() throws remoteexception{
super();
}

public void hello(string s) throws remoteexception{
system.out.println("client name " + s);
}

public static void main(string argv[]){
system.setsecuritymanager(new rmisecuritymanager());
try{
karaokebox box = new karaokeboximpl();
java.rmi.naming.rebind("karaokebox1", box);
}
catch(exception e){e.printstacktrace();}
}
}

以 下 是 源 代 码 必 要 的 修 改。 在rmi 中, 远 程 对 象 用 指 定 的 名 字(rebind.bind) 注 册。 虽 然 这 些 名 字 不 需 在 源 代 码 中 指 定, 象horb,rmi 使 用 对 象 进 行 远 程 对 象 操 作, 这 些 对 象 称 为stub( 与horb 中 的“ 代 理” 等 同) 和skeleton.

创 建 运 行 环 境

rmi 有 等 同 于horb 编 译 器 相 应 部 分 的 功 能, 这 些 功 能 自 动 创 建stub 和skeleton.

1.> javac client.java karaokebox.java karaokeboximpl.java 创 建

client.class

karaokebox.class

karaokeboximpl.class.
2.> rmic karaokeboximpl 创 建

karaokeboximpl_stub.class

karaokeboximpl_skel.class
3. 将client.class、karaokebox.class 和karaokeboximpl_stub.class 拷 贝 到 客 户 机, 将karaokebox.class、karaokeboximpl.class、karaokeboximpl_stub.class 和karaokeboximpl_skel.class 拷 贝 到 服 务 器( 在 客 户 机 和 服 务 器 上 必 须 安 装rmi).

运 行 过 程

1. 在 服 务 器 上 启 动rmi 注 册。

2. 服 务 器 上 启 动karaokeboximpl 对 象。

3. 在 客 户 机 上 以 字 符 串“junzo” 作 为 参 数 启 动client。

4. 结 果“client name junzo” 显 示 在 服 务 器 上。

运 行 结 果 如 图5 所 示。

图5:rmi 运 行 结 果

基 础 对 象 模 型 介 绍
这 部 分 用 上 面 的 源 代 码 说 明horb 和rim 的 基 础 对 象 模 型。 基 础 对 象 模 型 是 指 当 一 个 远 程 对 象 产 生 和 使 用 时, 给 远 程 对 象 用 户 的 视 图。 在 基 础 对 象 模 型 方 面,horb 和rmi 相 差 很 大。

产 生 模 型[horb,dcom]

产 生 模 型 提 供 与 面 向 对 象 编 程 一 样 的 实 例 创 建 方 法。 参 看 列 表3 中 加 入 的 部 分(horb 客 户 机 源 代 码)。 下 面 的 列 表 包 括 了 产 生karaokebox_proxy 的 源 代 码。

代 码 1: 代 理 对 象 创 建

karaokebox_proxy box = new karaokebox_proxy("horb://yourhostname");

回 忆 一 下,karaokebox 实 例 也 是 它 的 一 个 运 行 结 果。 换 句 话 说, 如 果 你 把karaokebox_proxy 当 作karaokebox 使 用, 就 可 以 用 面 向 对 象 编 程 中 通 常 的 实 例 产 生 过 程 一 样 的 方 法 创 建 远 程 对 象。 如 图 6 所 示。

图 6:horb 产 生 模 型

连 接 模 型[corba(java idl)、rmi、horb、pdo(nextstep)]

连 接 模 型 用 来 连 接 先 前 由 服 务 器 产 生 的 对 象。 用 连 接 模 型, 客 户 机 不 象 在 产 生 模 型 中 那 样 简 单 地 创 建karaokebox 实 例, 而 是 由 服 务 器 先 创 建 对 象。

将rmi 的 运 行 过 程 与horb 的 运 行 过 程 比 较, 很 明 显, 服 务 器 启 动karaokeboximpl 是 为 了 客 户 机 能 够 启 动client, 如 图7 所 示。

图7:rmi 连 接 模 型

下 面 的 列 表 包 括 允 许 客 户 机 连 接 远 程 对 象 的 源 代 码

代 码2: 连 接 远 程 对 象

karaokebox box = (karaokebox)naming.lookup("rmi://yourhostname/karaokebox1");

在rmi 中, 在 服 务 器 源 代 码 中 加 入 源 代 码( 列 表5 和 列 表6) 的 原 因 是 必 须 创 建main() 方 法, 以 便 加 入 产 生 远 程 对 象 的 代 码。

几 乎 所 有 的 分 布 式 对 象 技 术 都 提 供 连 接 模 型。horb 既 支 持 产 生 模 型 又 支 持 连 接 模 型。 连 接 模 型 的 一 个 问 题 是 客 户 机 只 能 连 接 由 服 务 器 产 生 的 对 象。 为 解 决 此 问 题, 使 用 了 一 种 技 术, 在 返 回 客 户 机 之 前 由 服 务 器 创 建 客 户 机 请 求 的 远 程 对 象。 以 下 是 这 种 技 术 的 一 个 例 子。

代 码3: 创 建 客 户 机 请 求 的 远 程 对 象

public karaokebox getobject() throws remoteexception{
karaokebox box = null;
try{
box = new karaokeboximpl("karaokebox" + instanceno );
}
catch(exception e){e.printstacktrace();}
return box;
}

远 程 消 息
在rmi 和horb 中, 在 远 程 对 象 可 用 后 发 送 一 个 远 程 消 息 的 方 法 几 乎 是 一 样 的。 图8 显 示 了 调 用hello() 方 法 和 往 服 务 器 拷 贝 一 个 字 符 串 实 例( 作 为hello() 方 法 的 参 数)。

图8: 远 程 消 息

在 此 处 理 中, 分 布 式 对 象 系 统 将string 接 口 转 化 为 简 单 的 数 据 流, 并 用 低 级 的socket 类 将 数 据 发 送 给 服 务 器。 服 务 器 将string 类 恢 复 成 以 前 的 形 式, 这 种 机 制 称 为“marshalling” 和“unmarshalling”。

现 在 问 题 是: 一 个 新 创 建 的、 独 立 的 类 实 例 能 否 作 为 一 个 远 程 消 息 参 数 或 一 个 返 回 值 ? 答 案 在 下 面 关 于 对 象 传 递 的 解 释 中。

对 象 传 递
将 对 象 实 例 作 为 一 个 远 程 方 法 的 参 数 传 递 或 作 为 一 个 远 程 方 法 的 返 回 值 称 为“ 对 象 传 递”。 作 为 例 子, 我 们 调 用karaokebox 的getmusic() 方 法,( 图9)。 客 户 机 作 为 参 数 传 送 歌 曲 选 择 数, 作 为 返 回 值 接 收 相 应 的music 对 象。

图9:music 对 象 来 自 服 务 器

1. 由horb 传 递 对 象

首 先 我 们 提 供 一 个 使 用horb 的 调 用 例 子。 在karaokebox 中 加 入 了 注 册getmusic() 方 法 的 构 造 器, 并 且 在 初 始 化 时 为 十 首 歌 加 入music 对 象。

列 表7:music 对 象 传 递(karaokebox.java)[horb]

import java.util.*;

class karaokebox{
hashtable musicbox = new hashtable();
public karaokebox(){
for(int i=0;i <10;i++){ musicbox.put( new integer(i), new music(i,"music" + i) ); // register music } } public void hello(string s){ system.out.println("client name " + s); } public music getmusic(int select_no){ music music="(music)musicbox.get(new" integer(select_no)); return music; // return music for specified song selection number } }
下 面 建 立music 类, 如 列 表8 所 示。 注 意 在horb 的 当 前 版 本 中, 在 对 象 中 只 有 公用 的“ 友 好” 属 性( 友 好 属 性 是 没 有 指 定 为 公 用 或 者 私 有 的 属 性) 才 能 传 递。这 限 制 在 支 持jdk 1.1 的horb 下 一 版 本 中 可 能 会 被 取 消。

列 表8:music 数 据 管 理 类(music.java)[horb]

public class music{
int no = 0;
string title = "";
string musicdata = "";

final static string[] sounds = {"tan", "bom", "tata", "ra-ra"};

public music(){}

public music(int no,string title){
this.no = no;
this.title = title;
for(int i=0;i <8;i++){ musicdata +="sounds[(int)(math.random()" * 4)] ; // create song (laugh) } system.out.println("new .." + title + ": " + musicdata ); } public int getno(){ return no; } public string gettitle(){ return title; } public void play(){ system.out.println("start> " + musicdata + " --> stop");
}
}

注 意, 在horb 当 前 版 本, 只 能 传 递 不 包 括 保 护 或 私 有 成 员 的 对 象 实 例, 这 一 限 制 在 支 持jdk1.1 的horb 下 一 版 本 中 可 能 会 被 取 消。 就 象 对hello() 方 法 一 样, 接 收music 对 象 的 代 码 加 入 到client 源 代 码 中。

列 表9: 接 收music 对 象 的 版 本(client.java)[horb]

import horb.orb.*;

class client{
public static void main(string argv[]){
string name = (argv.length == 1) ? argv[0] : "-";
karaokebox_proxy box = new karaokebox_proxy("horb://kinta");
box.hello(name);
for(int i=0;i <10;i++){ music m="box.getmusic(i);" // object is copied from server system.out.print("no." + m.getno() + " [" + m.gettitle() + "] "); m.play(); } } }

创 建 运 行 环 境
用horb 命 令 编 译music.java 和karaokebox.java 和 用javac 编 译client.java 的 过 程 如 下。 注 意music.java 必 须 用horb 编 译。 如 不 用horb 传 递 对 象, 必 须 用 一 个 代 理。 为 了 以 后 简 单, 确 定 按 下 面 的 方 法 指 定horb 编 译 器 选 项, 使 之 不 产 生 不 必 要 的 源 代 码 和 类。

1.>horbc -delete -proxyonly music.java 创 建

music.class

music_proxy.class.
2.>horbc -delete karaokebox.java 创 建

karaokebox.class

karaokebox_proxy.class

karaokebox_skeleton.class
3.>javac client.java 创 建

client.class

horbc 选 项:
-proxyonly 产 生 一 个proxy 类, 不 产 生skeleton 类。

-delete 删 除skeleton 和proxy 源 代 码。

运 行 过 程

1. 在 服 务 器 上 启 动horb 精 灵。

2. 在 客 户 机 上 用 字 符 串“junzo” 作 为 参 数 启 动client

3. 十 个 音 乐 数 据 项 显 示 在 服 务 器 和 客 户 机 上。

运 行 结 果 如 图10 所 示。

图10:horb 运 行 结 果( 对 象 传 递)

2. 用rmi 传 递 对 象

第 一 步 是 增 加karaokebox 加 载, 以 及 和 用horb 一 样,getmusic() 方 法 和music 对 象 注 册 的 代 码。 另 外,karaokebox 和karaokeboximpl 的 源 代 码 也 必 须 修 改( 参 看 列 表10 和 列 表11)。

列 表10:karaokebox 接 口(karaokebox.java)[rmi]

interface karaokebox extends java.rmi.remote{
public void hello(string s) throws java.rmi.remoteexception;
public music getmusic(int select_no) throws java.rmi.remoteexception;
}

列 表11:music 对 象 传 递(karaokeboximpl.java)[rmi]

import java.rmi.*;
import java.rmi.server.unicastremoteobject;
import java.util.hashtable;

public class karaokeboximpl extends unicastremoteobject implements karaokebox{
private hashtable musicbox = new hashtable();
public karaokeboximpl() throws remoteexception{
super();
for(int i=0;i <10;i++){ musicbox.put( new integer(i), new music(i,"music" + i) ); // register music } } public void hello(string s) throws remoteexception{ system.out.println("client name " + s); } public music getmusic(int select_no) throws remoteexception{ music music="(music)musicbox.get(new" integer(select_no)); return music; // return music for specified song selection number } public static void main(string argv[]){ try{ karaokebox box="new" karaokeboximpl(); system.setsecuritymanager(new rmisecuritymanager()); java.rmi.naming.rebind("karaokebox1", box); } catch(exception e){e.printstacktrace();} } }
rmi 对 象 传 递 中 使 用 了jdk1.1 的 串 行 化 功 能。music 类 必 须 实 现java.io.serializable java 接 口( 参 看 列 表12)。 不 象horb,rmi 允 许 传 递 有 私 有 成 员 的 对 象。

列 表12:music 数 据 管 理 类(music.java)[rmi]

public class music implements java.io.serializable{
private int no = 0;
private string title = "";
private string musicdata = "";
private final static string[] sounds = {"tan", "bom", "tata", "ra-ra"};

public music(int no,string title){
this.no = no;
this.title = title;
for(int i=0;i <8;i++){ musicdata +="sounds[(int)(math.random()" * 4)] ; // compose song (laugh) } system.out.println("new .." + title + ": " + musicdata ); } public int getno(){ return no; } public string gettitle(){ return title; } public void play(){ system.out.println("start> " + musicdata + " --> stop");
}
}

与horb 一 样, 接 收music 对 象 的 代 码 加 到 了 客 户 机 的 源 代 码 中, 如 列 表13 所 示。

列 表13: 接 收 版 本 的music 对 象(client.java)[rmi]

class client{
public static void main(string argv[]){
string name = (argv.length == 1) ? argv[0] : "-";
try{
karaokebox box = (karaokebox)java.rmi.naming.lookup("rmi://kinta/karaokebox1");
box.hello(name);
for(int i=0;i <10;i++){ music m="box.getmusic(i);" system.out.print("no." + m.getno() + " [" + m.gettitle() + "] "); m.play(); } } catch(exception e){e.printstacktrace();} } }
创 建 运 行 环 境

不 象 用horb, 而 与 往 常 一 样 用javac 编 译music.java

1.> javac music.java client.java karaokebox.java karaokeboximpl.java

2.> rmic karaokeboximpl

运 行 过 程

1. 在 服 务 器 上 启 动rmi 注 册。

2. 在 服 务 器 上 启 动karaokeboximpl 远 程 对 象。

3. 十 个 音 乐 数 据 项 显 示 在 服 务 器 上。

4. 在 客 户 机 上 以 字 符 串“junzo” 作 为 参 数 启 动client。

5. 十 个 音 乐 数 据 项 显 示 在 客 户 机 上。 运 行 结 果 如 图11 所 示( 在 示 例 代 码 中,“lookup”( 第 四 步) 必 须 在“rebind”( 第 三 步) 结 束 后 运 行)。

图11:rmi 运 行 结 果( 对 象 传 递)

分 布 式 应 用 程 序 的 设 计
以 下 是 在 设 计 分 布 式 应 用 程 序 时 需 要 考 虑 的 几 点:

理 解 产 品 的 特 征

在 开 发 分 布 式 应 用 程 序 时 重 要 的 一 点 是 掌 握 使 用 的 分 布 式 对 象 的 一 般 特 征。 最 好 的 办 法 是 将 你 的 产 品 与 其 他 的、 已 存 在 的 产 品 比 较。 另 外, 还 需 要 理 解 产 品 的 概 念。 例 如horb 追 求 一 种 无 缝 的、 分 布 式 的 面 向 对 象 环 境, 所 以 列 表1 中 介 绍 的karaokebox 类 无 需 为 远 程 服 务 器 设 计 而 修 改。 另 外, 使 用karaokebox 类 的 客 户 机 与 本 地 对 象 一 样 ─ ─ 调 用new。 即 使 在 远 程 方 法 调 用 时, 程 序 员 在 编 码 时 无 需 使 用 异 常 处 理。

比 较 而 言,rmi 要 求 程 序 员 按 照 精 确 的 规 则 设 计 分 布 式 对 象, 以 提 高 软 件 的 整 体 可 靠 性。 例 如 设 计 远 程 对 象 时, 程 序 必 须 使 用java 接 口, 与 本 地 方 法 一 样 对 对 象 明 确 分 类。 另 外, 在 远 程 方 法 调 用 中, 程 序 员 必 须 处 理 异 常。 与horb 的 另 一 个 差 别 是 父 类 是 在 远 程 对 象 中 决 定 的。

若 要 问 哪 一 个 是 当 前 最 好 的 方 案, 我 们 更 倾 向horb 网 络 无 缝 的 概 念。 当 然, 每 个 人 都 有 个 人 的 偏 爱, 未 必 能 有 一 个 客 观 的 评 价。horb 也 提 供 很 高 的 可 靠 性, 而rmi 和horb 一 样, 一 但 你 习 惯 了 它 也 会 很 容 易 使 用。

这 时 与 其 讨 论 谁 优 谁 劣, 不 如 客 观 地 比 较horb 和rmi。 这 样 我 们 便 可 以 理 解 所 使 用 的 分 布 式 对 象 技 术 创 造 者 的 目 的。 在 弥 补 其 不 足 时, 理 解 软 件。 同 时, 洞 查 分 布 式 对 象 未 来 的 形 式。 总 之, 符 合 发 展 趋 势 的 便 是 最 好 的 方 案。

明 确 指 出 分 布 式 处 理 的 目 标

决 定 哪 一 项 设 为 远 程 对 象 是 很 重 要 的 一 点。 将 单 机 内 存 对 象 扩 展 到 网 络 上 便 成 了 分 布 式 对 象。 设 计 远 程 对 象 时, 程 序 员 还 要 考 虑 涉 及 到 的 其 他 问 题。 具 体 地 说, 程 序 员 必 须 考 虑 诸 如 在 远 程 处 理 时 尽 量 减 少 网 络 传 输 量 和 使 客 户 机 与 远 程 对 象 接 口 尽 可 能 小 等 问 题。 建 立 一 个 系 统 时, 为 了 有 一 个 平 衡 的 设 计, 必 须 考 虑 在 网 络 中 包 括 分 布 式 对 象 的 需 求。

正 确 使 用 对 象 传 递 和 远 程 对 象

正 确 的 使 用 对 象 传 递 和 远 程 对 象 也 是 很 重 要 的 一 点。 远 程 对 象 是 通 过 代 理 访 问 服 务 器 对 象 的 一 种 方 法。 例 如, 上 面 介 绍 的music 对 象 的 例 子, 处 理 是 通 过 将music 对 象 作 为 远 程 对 象 装 载, 而 不 是 使 用 对 象 传 递 实 现 的。 只 有corba 支 持 这 种 方 法。

对 象 传 递 允 许 程 序 员 减 少 通 信, 因 为 对 象 被 拷 贝 到 了 客 户 机 上。 远 程 对 象 更 适 合 用 于 需 要 直 接 利 用 服 务 器cpu 资 源 或 服 务 器 数 据 资 源 的 情 况。 从 数 据 一 致 性 的 观 点 来 说, 当 客 户 机 只 需 要 对 象 的 一 些 属 性, 而 不 是 整 个 对 象 时, 更 适 合 用 远 程 对 象。 在 服 务 器 对 象 属 性 总 由 服 务 器 处 理 来 修 改 的 模 型 中, 也 更 适 合 用 远 程 对 象。

作 为 面 向 对 象 方 法 学 的 一 环
分 布 目 标 清 楚 的 设 计 应 该 用 面 向 对 象 的 分 析 无 缝 地 实 现。 将 来, 网 络 分 布 式 对 象 模 型 可 能 会 成 为 面 向 对 象 方 法 学 中 开 发 过 程 的 一 环。 在 由 作 者 开 发 的 面 向 对 象 方 法 学“drop” 中(http://www.njk.co.jp/otg/), 这 类 环 境 通 过 使 用 在 对 象 分 析 中 称 为“ 重 用 基 础 模 型” 的 对 象 分 类 方 法 来 实 现。 重 用 基 础 模 型 是 一 种 分 类 方 法, 将 需 求 分 析 阶 段 的 对 象 分 成 不 同 的 角 色, 如view( 视 图)、process( 处 理) 和data( 数 据 管 理)。 并 且 分 清 重 用 范 围, 如generic( 通 用)、addparts( 系 统 公 用) 和app( 应 用 程 序 专 用), 这 种 模 式 可 用 来 对 需 求 分 析 阶 段 的 对 象 分 类, 并 且 转 换 为 无 缝 的 分 布 式 对 象 设 计。

用corba 设 计
这 部 分 介 绍 一 个music 类 的 例 子, 它 是corba 设 计 的。corba 使 用 远 程 对 象 来 装 载music 对 象。 在 此 情 况 下, 当 客 户 机 调 用music 对 象 的 参 考( 在corba 中 为 代 理 对 象) 的play() 方 法 时,play() 方 法 由 服 务 器 运 行。 这 是 不 方 便 的。 实 际 上,music 类 的play() 方 法 必 须 修 改 为 命 名 为getmusicdata() 的 方 法。music 的 数 据 结 构( 而 不 是 对 象) 必 须 传 递 到 客 户 机 上。 客 户 机 必 须 创 建 一 个 新 的player 类。 使 用player 对 象 来 修 改 使 用music 数 据 的 设 计。 换 句 话 说,play() 方 法 不 能 进 入 到 分 布 在 服 务 器 的 对 象 中( 参 看 图12)

图12: 将 音 乐 数 据 传 给 播 放 器

在 此 例 子 中,music 类 变 成 了 一 个 数 据 管 理 数 据 对 象,player 类 变 成 了 一 个 播 放 处 理。 换 句 话 说“drop” 不 提 倡 将 称 为play() 的 播 放 处 理 指 派 给music 数 据 管 理 对 象 的 设 计。( 在 本 文 中, 我 们 将play() 指 派 给music, 以 简 化 说 明。)

通 过 在 分 析 的 开 始 便 将 数 据 管 理 数 据 和 数 据 操 作 过 程 分 开, 以 及 集 中 于 数 据 管 理 对 象, 我 们 能 解 决 因 为 分 布 式 对 象 产 品 的 差 别 而 不 得 不 修 改 设 计 方 法 的 问 题。 同 时 我 们 能 将 调 用 方 法 排 除 在 基 本 问 题 的 分 析 阶 段。

去 年, 作 者 所 属 的 开 发 组 使 用 了“drop” 开 发 过 程 开 发 了 一 个 航 空 订 票 系 统。 在 系 统 活 动 期 间, 通 过 使 用 称 为“concept” 的 概 念, 同 时 执 行 中 间 软 件 认 证 和 网 络 框 架 检 查, 转 变 了 分 布 式 对 象 或 数 据 库 的 调 用 方 法。

现 在, 这 个 开 发 组 通 过 讨 论 会 和web 站 点, 将 航 空 系 统 用 来 介 绍 基 于 分 布 式 对 象 的 网 络 系 统 的 设 计。 今 年, 我 们 计 划 用 讨 论 会 来 培 训 将 来 支 持 软 件 业 务 的 学 员。

分 布 式 对 象 编 程 的 目 标
分 布 式 对 象 编 程 的 目 标 是 将 基 于 单 机 的 面 向 对 象 机 制 扩 展 到 网 络, 实 现 此 目 标 可 以 归 结 为 以 下 三 个 技 术 概 念:

1. 网 络 透 明 的 面 向 对 象 操 作 - 允 许 用 正 常 的 面 向 对 象 编 程 方 法 操 作 对 象。

2. 对 象 位 置 透 明 性 - 提 供 一 个 隐 藏 网 络 上 对 象 位 置( 服 务 器) 的 机 制。

3. 语 言 独 立、orb 产 品 独 立 的 环 境 - 提 供 一 个 不 依 赖 于 特 定 语 言 和 产 品 的 环 境。

第 一 个 概 念, 网 络 透 明 的 面 向 对 象 操 作 是horb 大 力 提 倡 的。 然 而,horb 不 支 持 上 面 的 概 念2 或3 - 对 象 位 置 的 透 明 性 和 语 言 独 立、orb 产 品 独 立 的 环 境。

horb 概 念 将 分 布 式 对 象 当 作 面 向 对 象 的 扩 充。rmi 也 不 支 持 概 念2 或3, 然 而rmi 概 念 接 近 于corba 对 象 模 型, 似 乎 与horb 一 样 也 强 调 以 上 所 列 的 第 一 个 概 念。 另 一 方 面,corba 大 力 提 倡 概 念2 和3 。 自1990 年 以 来, 对 象 管 理 集 团(omg) 一 直 在 发 展corba, 使 之 成 为 分 布 式 对 象 编 程 的 全 球 标 准。 当 前 的corba 版 本 为2.0。 一 个 称 为java idl( 接 口 定 义 语 言)、 符 合corba 的orb 捆 绑 在jdk 1.1 中。corba 概 念, 例 如 开 放 软 件 基 金 会(osf) 的 远 程 过 程 调 用(rpc) 和 分 布 式 计 算 环 境(dce), 将 分 布 式 对 象 看 作 是 网 络 计 算 的 扩 充。 因 此,corba 重 点 在 于 技 术 概 念2 和3, 它 们 面 向 大 规 模 的、 分 布 的 网 络 系 统。 然 而, 仍 不 能 说corba 已 实 现 了“ 网 络 透 明 对 象 操 作” 的 目 标。

例 如, 我 们 看 看corba 的 公 用 语 言-idl。 必 须 用 此 语 言 声 明 远 程 消 息。idl 是 一 个 重 要 的 框 架, 允 许 在 包 括 不 同 的orb 和 语 言 的 环 境 中 进 行 协 同 对 象 操 作。 然 而, 使 用idl 类 似 于 开 发 一 个 名 为esperanto 的 语 言 的 概 念, 它 允 许 全 球 的 每 一 个 人 用 一 种 公 用 语 言 交 谈。 使 用 一 种 公 用 语 言 可 能 会 导 致 一 个 国 家 成 熟 的 发 展 减 弱( 例 如 一 种 语 言 成 熟 的 面 向 对 象 功 能)。 而 且, 如 果orb 开 发 商 完 全 实 现corba 大 部 分 的 规 范, 将 面 临 无 穷 无 尽 的 工 作。

虽 然, 每 一 个 分 布 式 对 象 工 具 有 不 同 的 结 构, 但 是 下 一 代 分 布 式 对 象 应 用 程 序 可 能 会 以 很 好 地 平 衡 如 上 所 述 的 三 个 技 术 概 念 为 特 征。 为 实 现 这 一 步 的 工 作 已 经 开 始, 一 些corba 产 品 对 用 户 隐 藏idl, 也 有 一 些 非corba 产 品 支 持corba 的internet 交 互 对 象 请 求 代 理 协 议(iiop), 以 便 能 够 连 接corba。 虽 然 这 些 工 作 被 认 为 是 一 些 调 整, 但 是 它 们 可 能 是 产 生 下 一 代 分 布 式 对 象 产 品 的 开 发 过 程 不 可 分 割 的 部 分。

结 论
本 文 叙 述 了 基 于java 的 分 布 式 对 象 技 术rmi 和horb。 有 很 多 我 们 想 介 绍 的 功 能, 例 如rmi 和horb 支 持 双 向 消 息 通 信 和horb 支 持 的 异 步 通 信, 以 及 很 多 新 的 符 合corba 的、 基 于java 的 分 布 式 对 象 产 品, 但 是 限 于 篇 幅, 我 们 就 到 这。 虽 然 分 布 式 对 象 编 程 并 不 难, 但 是 它 是 使 复 杂 网 络 应 用 程 序 易 于 理 解 的 领 先 技 术。

扫描关注微信公众号