初识RMI

    在一次听课中第一次听说了RMI协议,对于我们这些没有接触过EJB的程序员来说感觉RMI是一个挺新奇的东西,居然能够让某个java虚拟机上的对象调用另一个java虚拟机中的对象上的方法,感觉挺有用的,就回来研究了下RMI的原理和用法。

    百度上这么解释RMI:RMI是Java的一组拥护开发分布式应用程序API。RMI使用Java语言接口定义了远程对象,它集合了Java序列化和Java远程方法协议(Java Remote Method Protocol)。简单地说,这样使原先的程序在同一操作系统的方法调用,变成了不同操作系统之间程序的方法调用,由于J2EE是分布式程序平台,它以RMI机制实现程序组件在不同操作系统之间的通信。

rmi的详细介绍可以参开 http://docs.huihoo.com/java/rmi/whitepage/index.html 

下面根据看到的一个简单例子来让我们简单的使用rmi。

第一步:首先创建一个java project工程,在工程中先定义一个远程接口IHello,注意该远程接口必须继承Remote接口,其中需要远程调用的方法必须抛出RemoteException异常,且远程接口必须为public。代码如下:

package com.rmi.demo;

import java.rmi.Remote;
import java.rmi.RemoteException;

/** 
* 定义一个远程接口,必须继承Remote接口,其中需要远程调用的方法必须抛出RemoteException异常 
*/ 
public interface IHello extends Remote { 

    /**
     * @return 简单的返回"hello world"字符串
     * @throws RemoteException
     */
    public String helloWorld() throws RemoteException; 

    /** 
     * 一个简单的业务方法,根据传入的人名返回相应的问候语 
     * @param someBodyName  人名 
     * @return 返回相应的问候语 
     * @throws java.rmi.RemoteException 
     */ 
    public String sayHelloToSomeBody(String someBodyName) throws RemoteException; 
}

第二步:实现该接口。注意实现接口必须继承UnicastRemoteObject,实现代码如下:

package com.rmi.demo;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

/** 
* 远程的接口的实现 
*/ 
public class HelloImpl extends UnicastRemoteObject implements IHello { 

	/** 
     * 因为UnicastRemoteObject的构造方法抛出了RemoteException异常,
     * 因此这里默认的构造方法必须写,必须声明抛出RemoteException异常 
     * 
     * @throws RemoteException 
     */ 
    public HelloImpl() throws RemoteException { 
    } 

    /** 
     * @return 返回"hello world"字符串 
     * @throws java.rmi.RemoteException 
     */ 
    public String helloWorld() throws RemoteException { 
        return "hello world!"; 
    } 

    /** 
     * 一个简单的业务方法,根据传入的人名返回相应的问候语 
     * 
     * @param someBodyName 人名 
     * @return 返回相应的问候语 
     * @throws java.rmi.RemoteException 
     */ 
    public String sayHelloToSomeBody(String someBodyName) throws RemoteException { 
        return "你好," + someBodyName + "!"; 
    } 
}

第三步:创建一个服务类,它的作用是创建RMI注册表,启动RMI服务,并将远程对象注册到RMI注册表中,实现代码如下:

package com.rmi.demo;

import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;

/** 
* 创建RMI注册表,启动RMI服务,并将远程对象注册到RMI注册表中。 
*/ 
public class HelloServer { 
    public static void main(String args[]) { 

        try { 
            //创建一个远程对象 
            IHello rhello = new HelloImpl(); 
            //本地主机上的远程对象注册表Registry的实例,并指定端口为8888,
            //这一步必不可少(Java默认端口是1099),必不可缺的一步,缺少注册表创建,则无法绑定对象到远程注册表上 
            LocateRegistry.createRegistry(8888); 

            //把远程对象注册到RMI注册服务器上,并命名为RHello 
            //绑定的URL标准格式为:rmi://host:port/name(其中协议名可以省略,下面两种写法都是正确的) 
            Naming.bind("rmi://localhost:8888/RHello",rhello); 
            //Naming.bind("//localhost:8888/RHello",rhello); 

            System.out.println(">>>>>INFO:远程IHello对象绑定成功!"); 
        } catch (RemoteException e) { 
            System.out.println("创建远程对象发生异常!"); 
            e.printStackTrace(); 
        } catch (AlreadyBoundException e) { 
            System.out.println("发生重复绑定对象异常!"); 
            e.printStackTrace(); 
        } catch (MalformedURLException e) { 
            System.out.println("发生URL畸形异常!"); 
            e.printStackTrace(); 
        } 
    } 
}

第四步:创建另一个java project工程,这个工程用来远程调用第一个工程的方法,这个工程只需包含2个类文件,IHello远程接口,代码同上。还需要一个类HelloClient类,它的作用是远程调用第一个工程的方法,实现代码如下:

package com.rmi.demo;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

/** 
* 客户端测试,在客户端调用远程对象上的远程方法,并返回结果。 
*/ 
public class HelloClient { 
    public static void main(String args[]){ 
        try { 
            //在RMI服务注册表中查找名称为RHello的对象,并调用其上的方法 
            IHello rhello =(IHello) Naming.lookup("rmi://localhost:8888/RHello"); 
            System.out.println(rhello.helloWorld()); 
            System.out.println(rhello.sayHelloToSomeBody("rmi")); 
        } catch (NotBoundException e) { 
            e.printStackTrace(); 
        } catch (MalformedURLException e) { 
            e.printStackTrace(); 
        } catch (RemoteException e) { 
            e.printStackTrace();   
        } 
    } 
}

测试:

先运行HelloServer的main方法,如果输出【>>>>>INFO:远程IHello对象绑定成功!】,则说明已经成功启动RMI服务

然后运行HelloClient的main方法,然后会输出:

hello world!
你好,rmi!

则说明测试成功,一个应用成功的调用了另外一个应用的方法,并得到返回值了。

ps:在调试过程中碰到一个异常,如果二个应用的远程接口的package的路径不一样的时候会抛出如下异常:java.lang.ClassNotFoundException: com.rmi.demo.IHello (no security manager: RMI class loader disabled),这是因为在将远程对象注册到RMI注册表中时,会附带上package信息,如果服务端与客户端的远程接口所放得包不一样,就会找不到对应的实现接口,抛出异常。

参考博客:

http://lavasoft.blog.51cto.com/62575/91679/

http://docs.huihoo.com/java/rmi/whitepage/index.html

http://www.233.com/Java/jichu/20070214/151627705.html

你可能感兴趣的:(rmi)