本文是对RMI-IIOP入门的探究,旨在了解其开发过程,形成感性认识,进而了解其原理和应用。
RMI 和 CORBA 常被视为相互竞争的技术,因为两者都提供对远程分布式对象的透明访问。但这两种技术实际上是相互补充的,一者的长处正好可以弥补另一者的短处。RMI 和 CORBA 的结合产生了 RMI-IIOP,RMI-IIOP 是企业服务器端 Java 开发的基础。
RMI-IIOP 很强大的功能之一是,它让您编写纯 Java 客户机/服务器实现而不丧失 RMI 类序列化的灵活性。RMI-IIOP 通过覆盖 Java 序列化并在导线上将 Java 类转换成 IIOP 做到这一点。在另一端,Java 类被作为 IIOP 从导线上读下来,接着创建这个类的一个新实例(使用反射),类的所有成员的值都完整无缺 ― 瞧:这就是 IIOP 上的 Java 序列化!
(以上两段描述来自IBM:
http://www.ibm.com/developerworks/cn/java/j-rmi-iiop/,本例的诞生也从中受到启发。)
看来上面觉得RMI-IIOP技术很牛,但是,为什么这么牛的技术在网上就没有一个完整的可运行实例呢,有一篇文章视乎可以运行,但是按照作者的操作结果总是报错。
再回头看看SUN官方的文档,
http://java.sun.com/javase/6/docs/technotes/guides/rmi-iiop/rmiiiopexample.html,冠冕堂皇的给出了一个HelloWorld的例子,可是TNND,连编译都不能通过,Google一下,有几万个问及此问题的文章,可是没有一个解决方案。不信你试试!
搜索关键字:tPOA.activate_object_with_id( id, tie )
对SUN的文档,只能用一个遗憾的感叹号来表达此刻的心情。
抛开官方例子,另外想想办法,最终写出了下面可运行的HelloWorld!
项目目录结构如下:
rmiiiopstart
└─src
└─lavasoft
└─rmiiiop
└─src
└─lavasoft
└─rmiiiop
步骤如下:
一、定义远程接口
package lavasoft.rmiiiop;
import java.rmi.Remote;
import java.rmi.RemoteException;
/**
* 定义远程接口
*
* @author leizhimin 2009-12-9 14:11:34
*/
public interface Hello extends Remote {
/**
* 远程接口方法实现
*
* @param name 问候的人名
* @return 问候语
*/
String sayHello(String name) throws RemoteException;
}
import java.rmi.Remote;
import java.rmi.RemoteException;
/**
* 定义远程接口
*
* @author leizhimin 2009-12-9 14:11:34
*/
public interface Hello extends Remote {
/**
* 远程接口方法实现
*
* @param name 问候的人名
* @return 问候语
*/
String sayHello(String name) throws RemoteException;
}
二、实现远程接口(这个实现类也作为服务端)
package lavasoft.rmiiiop;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
import java.rmi.RemoteException;
/**
* 远程接口的实现类,必须继承PortableRemoteObject类
*
* @author leizhimin 2009-12-9 14:13:46
*/
public class HelloImpl extends PortableRemoteObject implements Hello {
/**
* 必须明确的创建一个构造方法,并抛出RemoteException异常
*/
public HelloImpl() throws RemoteException {
}
/**
* 远程接口方法实现
*
* @param name 问候的人名
* @return 问候语
*/
public String sayHello(String name) throws RemoteException {
return "Hello, " + name + "!";
}
public static void main(String[] args) {
try {
HelloImpl hello = new HelloImpl();
//创建一个名称上下文,并绑定远程对象
Context initialNamingContext = new InitialContext();
initialNamingContext.rebind( "HelloImpl", hello);
System.out.println( "Hello Server: Ready and Waiting...");
} catch (Exception e) {
e.printStackTrace();
}
}
}
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
import java.rmi.RemoteException;
/**
* 远程接口的实现类,必须继承PortableRemoteObject类
*
* @author leizhimin 2009-12-9 14:13:46
*/
public class HelloImpl extends PortableRemoteObject implements Hello {
/**
* 必须明确的创建一个构造方法,并抛出RemoteException异常
*/
public HelloImpl() throws RemoteException {
}
/**
* 远程接口方法实现
*
* @param name 问候的人名
* @return 问候语
*/
public String sayHello(String name) throws RemoteException {
return "Hello, " + name + "!";
}
public static void main(String[] args) {
try {
HelloImpl hello = new HelloImpl();
//创建一个名称上下文,并绑定远程对象
Context initialNamingContext = new InitialContext();
initialNamingContext.rebind( "HelloImpl", hello);
System.out.println( "Hello Server: Ready and Waiting...");
} catch (Exception e) {
e.printStackTrace();
}
}
}
三、开发客户端
package lavasoft.rmiiiop;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
/**
* 客户端应用
*
* @author leizhimin 2009-12-9 14:21:35
*/
public class HelloClient {
public static void main(String[] args) {
try {
//获取一个名称上下文
Context ic = new InitialContext();
//得到一个远程对象的引用
Object objRef = ic.lookup( "HelloImpl");
//强制转换为一个更具体的Hello接口对象
Hello hello = (Hello) PortableRemoteObject.narrow(objRef, Hello. class);
// 调用远程对象的方法
System.out.println( "收到来自服务器的消息: " + hello.sayHello( "张三") + "\n");
} catch (Exception e) {
e.printStackTrace();
}
}
}
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
/**
* 客户端应用
*
* @author leizhimin 2009-12-9 14:21:35
*/
public class HelloClient {
public static void main(String[] args) {
try {
//获取一个名称上下文
Context ic = new InitialContext();
//得到一个远程对象的引用
Object objRef = ic.lookup( "HelloImpl");
//强制转换为一个更具体的Hello接口对象
Hello hello = (Hello) PortableRemoteObject.narrow(objRef, Hello. class);
// 调用远程对象的方法
System.out.println( "收到来自服务器的消息: " + hello.sayHello( "张三") + "\n");
} catch (Exception e) {
e.printStackTrace();
}
}
}
四、写编译、生成代码、运行脚本
1、写编译、生成代码代码的脚本
build.bat
javac -d . lavasoft/rmiiiop/*.java
rmic -classpath . -iiop -d . lavasoft.rmiiiop.HelloImpl
rmic -classpath . -iiop -d . lavasoft.rmiiiop.HelloImpl
2、启动服务端脚本
runserver.bat
start orbd -ORBInitialPort 9999
java -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory -Djava.naming.provider.url=iiop: //localhost:9999 lavasoft.rmiiiop.HelloImpl
java -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory -Djava.naming.provider.url=iiop: //localhost:9999 lavasoft.rmiiiop.HelloImpl
3、客户端调用脚本
java -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory -Djava.naming.provider.url=iiop:
//localhost:9999 lavasoft.rmiiiop.HelloClient
将三个bat文件放到src下面。
五、编译执行
1、编译并生成代码
2、启动服务端
3、执行客户端
执行了三次,均成功调用并返回结果。
本文转自 leizhimin 51CTO博客,原文链接:http://blog.51cto.com/lavasoft/240666,如需转载请自行联系原作者