RMI-IIOP版的HelloWorld
 
本文是对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
 
 
步骤如下:
 
一、定义远程接口
 
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;
}
 
二、实现远程接口(这个实现类也作为服务端)
 
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();
                }
        }
}
 
三、开发客户端
 
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();
                }
        }
}
 
四、写编译、生成代码、运行脚本
 
1、写编译、生成代码代码的脚本
 
build.bat
javac -d . lavasoft/rmiiiop/*.java
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
 
3、客户端调用脚本
java -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory -Djava.naming.provider.url=iiop: //localhost:9999 lavasoft.rmiiiop.HelloClient
 
将三个bat文件放到src下面。
 
五、编译执行
 
1、编译并生成代码
RMI-IIOP版的HelloWorld_第1张图片
 
2、启动服务端
 
RMI-IIOP版的HelloWorld_第2张图片
 
3、执行客户端
 
RMI-IIOP版的HelloWorld_第3张图片
 
执行了三次,均成功调用并返回结果。