CORBA技术:工厂对象、对象持久化与RMI-IIOP详解
立即解锁
发布时间: 2025-08-17 02:29:09 阅读量: 2 订阅数: 7 


Java网络编程与文件处理入门
### CORBA 技术:工厂对象、对象持久化与 RMI - IIOP 详解
#### 1. 使用工厂对象
在实际应用中,客户端程序常常需要创建 CORBA 对象,而不仅仅是使用已经设置好的对象。实现这一目的的唯一途径是通过 ORB 上已发布的工厂对象接口。对于每种需要创建的对象类型,必须在 IDL 规范(在 ORB 上)中定义一个工厂对象接口,并在服务器上实现该接口。
通常,此类接口的命名约定是在要创建的对象类型名称后面添加“Factory”一词。例如,`Account` 接口的对象将由 `AccountFactory` 对象创建。`AccountFactory` 对象包含一个创建方法,允许连接的客户端创建 `Account` 对象。这个创建方法的名称可以任意指定,但为了方便起见,通常在要创建的对象类型前面加上“create”。因此,`AccountFactory` 的创建方法可以命名为 `createAccount`。
假设 `Account` 对象在创建时只需要一个账号和账户名称,那么 IDL 规范中的 `AccountFactory` 接口如下:
```java
interface AccountFactory
{
Account createAccount(in long acctNum,
in string acctName);
};
```
该方法的实现将使用 `new` 运算符来创建 `Account` 对象。与其他接口实现一样,此实现必须扩展由 `idlj` 生成的适当的 `ImplBase` 类(在这种情况下是 `_AccountFactoryImplBase`)。按照在实现类名称后面添加“Servant”的约定,我们将该实现命名为 `AccountFactoryServant`。其实现形式如下:
```java
class AccountFactoryServant
extends _AccountFactoryImplBase
{
public Account createAccount(int acctNum,
String acctName)
{
return (new AccountServant(
acctNum, acctName));
}
}
```
然而,这似乎只是将对象创建问题转移到了工厂接口上。连接的客户端无法创建工厂对象,那么它们如何访问这些对象中的创建方法呢?简单的答案是,服务器将为每个工厂接口创建一个工厂对象,并将该对象注册到 ORB 上。客户端随后可以获取该工厂对象的引用,并使用该对象的创建方法来创建 CORBA 应用程序对象。
假设客户端已经获得了服务器创建的 `AccountFactory` 对象的引用,并且该引用存储在变量 `acctFactoryRef` 中,那么客户端可以使用以下代码创建一个账号为 12345、账户名称为“John Andrews”的 `Account` 对象:
```java
Account acct = acctFactoryRef.createAccount(
12345,"John Andrews");
```
对于非持久对象,还应该定义销毁 CORBA 对象的方法(不过这里暂不涉及)。
#### 2. 示例:使用 Java IDL 实现对库存物品的平台无关访问
为了说明工厂接口及其关联的工厂对象的使用,下面通过一个具体示例进行详细介绍。
##### 2.1 创建 IDL 文件
创建一个名为 `StockItem.idl` 的文件,其中包含一个名为 `Sales` 的模块。该模块包含 `StockItem` 和 `StockItemFactory` 两个接口。`StockItem` 接口包含与单个库存物品相关的属性和操作,为了简化,属性包括库存代码和当前库存水平,操作包括增加和减少该库存物品的库存水平。由于库存代码不应更改,因此将其声明为只读属性。`StockItemFactory` 接口包含 `createStockItem` 方法,用于创建具有指定库存代码和库存水平的 `StockItem` 对象。`StockItem.idl` 的内容如下:
```java
module Sales
{
interface StockItem
{
readonly attribute string code;
attribute long currentLevel;
long addStock(in long incNumber);
long removeStock(in long decNumber);
};
interface StockItemFactory
{
StockItem createStockItem(in string newCode,
in long newLevel);
};
};
```
##### 2.2 编译 IDL 文件
由于客户端和服务器将在同一台机器上运行,因此使用 `-fall` 标志。执行 `idlj` 编译器的命令如下:
```bash
idlj –fall StockItem.idl
```
这将创建一个与模块名称相同的子目录(即 `Sales`),其中包含以下十二个文件(每个接口六个文件):
- `StockItem.java`
- `StockItemHelper.java`
- `StockItemHolder.java`
- `StockItemOperations.java`
- `_StockItemImplBase.java`
- `_StockItemStub.java`
- `StockItemFactory.java`
- `StockItemFactoryHelper.java`
- `StockItemFactoryHolder.java`
- `StockItemFactoryOperations.java`
- `_ StockItemFactoryImplBase.java`
- `_ StockItemFactoryStub.java`
##### 2.3 实现接口
遵循在接口名称后面添加“servant”的约定,创建 `StockItemServant` 和 `StockItemFactoryServant` 类,它们分别继承 `_StockItemImplBase` 和 `_StockItemFactoryImplBase` 类。代码如下:
```java
class StockItemServant extends _StockItemImplBase
{
private String code = "";
private int currentLevel = 0;
public StockItemServant(String newCode, int newLevel)
{
code = newCode;
currentLevel = newLevel;
}
public int addStock(int incNumber)
{
currentLevel += incNumber;
return currentLevel;
}
public int removeStock(int decNumber)
{
currentLevel -= decNumber;
return currentLevel;
}
public String code()
{
return code;
}
public int currentLevel()
{
return currentLevel;
}
public void currentLevel(int newLevel)
{
currentLevel = newLevel;
}
}
class StockItemFactoryServant
extends _StockItemFactoryImplBase
{
public StockItem createStockItem(String newCode, int newLevel)
{
return (new StockItemServant(newCode,newLevel));
}
}
```
这些类将与服务器代码放在同一个文件中。
##### 2.4 创建服务器
服务器程序名为 `StockItemServer.java`,它将包含上一步创建的服务类。该程序将导入 `Sales` 包以及以下三个标准 CORBA 包:
- `org.omg.CosNaming;`
- `org.omg.CosNaming.NamingContextPackage;`
- `org.omg.CORBA.`
```java
import Sales.*;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;
public class StockItemServer
{
public static void main(String[] args)
{
try
{
ORB orb = ORB.init(args,null);
StockItemServant stockServant =
new StockItemServant("S0001", 100);
orb.connect(stockServant);
StockItemFactoryServant factoryServant =
new StockItemFactoryServant();
orb.connect(factoryServant);
org.omg.CORBA.Object objectRef =
orb.resolve_initial_references("NameService");
NamingContext namingContext =
NamingContextHelper.narrow(objectRef);
NameComponent nameComp =
new NameComponent("Stock", "");
NameComponent[] stockPath = {nameComp};
namingContext.rebind(stockPath,stockServant);
NameComponent factoryNameComp =
new NameComponent("StockFactory", "");
NameComponent[] factoryPath =
{factoryNameComp};
namingContext.rebind(
factoryPath,factoryServant);
System.out.print("\nServer running...");
java.lang.Object syncObj =
new java.lang.Object();
synchronized(syncObj)
{
syncObj.wait();
}
}
catch (Exception ex)
{
System.out.println("*** Server error! ***");
ex.printStackTrace();
}
}
}
class StockItemServant extends _StockItemImplBase
{
//Code as shown in step 3 above.
}
class StockItemFactoryServant
extends _StockItemFactoryImplBase
{
//Code as shown in step 3 above.
}
```
##### 2.5 编译服务器和 IDL 生成的文件
在 `Sales` 目录的上一级目录中,在命令窗口中执行以下命令:
```bash
javac StockItemServer.java Sales\*.java
```
如有错误,需进行修正并重新编译。
##### 2.6 创建客户端
客户端程序名为 `StockItemClient.java`,它将导入 `Sales` 包以及 `org.omg.CosNaming` 和 `org.omg.CORBA` 包。除了执行上一个示例中客户端的步骤外,还将执行以下操作:
- 对已存在的 `StockItem` 对象进行多次方法调用,而不仅仅是对 `Hello` 对象进行一次调用。
- 获取服务器创建并注册的 `StockItemFactory` 对象的引用。
- 使用上述引用调用 `createStockItem` 方法创建一个新的 `StockItem` 对象。
- 调用新 `StockIte
0
0
复制全文
相关推荐










