`

Java远程调用RMI(Remote Method Invocation)

 
阅读更多

【转自:http://blog.csdn.net/lethorld/article/details/7089374#】

 

1.RMI和Java Remote Method Invocation

在讨论RMI之前,我们先看看网站的架构。典型的网站有一个服务提供商(Web Server),多个服务使用者(Web Client)。网站使用的是浏览器(Browser)作为客户端,也就是所说的BS架构(Browser-Server)。还有一种不是使用浏览器作为客户端的,比如说即时聊天工具(QQ、MSN)等,它们需要你在本地安装相应的客户端程序后才能运行,这就是所说的CS架构(Client-Server)。CS架构和BS架构相比较,BS的优势在于它能够有很好的移植和兼容性(只要你本地安装了浏览器,原则上你就能使用我的系统);而对于CS架构,个人觉得它的优势在于可操作性(客户端完全由自己开发,可以想怎么写就怎么写,完全不需要受到浏览器的约束)。
现在我们说说所谓的RMI,RMI全称为Remote Method Invocation,中文翻译为远程方法调用。指的是从本地调用服务器上的一组方法,服务器根据提交的信息(方法名、方法携带参数)计算得到结果、并将结果返回给调用者。Java Remote Method Invocation指的是在Java上实现上述机制。RMI可以理解成一种思想,一种架构,而JRMI则是这种思想或者架构的Java版本的实现。

2.浅谈如何实现RMI机制

好的机制需要屏蔽底层的实现细节。对于RMI的实现,需要做到:调用远程对象(Remote Object)和调用本地对象(Local Object)对于调用者来说没有任何区别。基于这个出发点,我们看看本地调用如何实现。

2.1 调用本地对象

首先我们需要定义一个Java类,该类有一个方法localCall。
package com.ztesoft.provisioning.local;

/**
 * 本地对象,用于被调用
 * @author Lethorld
 *
 */
public class LocalObject {
	/**
	 * 本地调用,用于测试
	 * @param arg 入参
	 * @return 返回
	 */
	public String localCall(String arg) {
		// TODO : do something.
		return arg;
	}
}
然后,我们写一个类用于调用这个本地对象。
    package com.ztesoft.provisioning.local;
    
    /**
     * 本地调用者
     * @author Lethorld
     *
     */
    public class LocalInvoker {
    	/**
    	 * 主函数
    	 * @param args 入参
    	 */
    	public static void main(String[] args) {
    		LocalObject object = new LocalObject();
    		String retn = object.localCall("Hello");
    		System.out.println(retn);
    	}
    }
    这样我们便完成了本地的一次对象调用。我们的运行main函数后,主程序会new一个LocalObject对象,并且调用该对象的localCall方法。localCall方法根据入参"Hello",返回相应的返回值。这里面没有做处理,所以返回的是Hello。
    OK,这段代码应该是所有只要稍微懂一点Java的人都能够看明白,并且很轻松地写出来的。那么,对于Java的远程调用,也就是上面所说的RMI,是否可以简单的把所有的local改成remote就OK了呢?答案是否定的。

    2.2 定义与实现分离

    要实现远程调用,首先必须考虑的是如何将方法的定义和方法的实现分离开。如果方法定义与实现不能相互分离,那么我们怎么能够将方法的实现放到服务器端,而仅仅在客户端上保存一个方法的声明呢?对于Java,要完成将定义与实现相分离的任务,我们自然而然地想到了接口(interface)这个工具。请看百度百科中对于Java接口的描述:“Java中的接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。”你看,这难道不就是我们想要的所谓的定义与实现相分离的特性吗?好吧,下面我们用接口来重写上面的例子。
    首先我们定以接口,接口的定义这里不赘述,也不属于本文准备详细阐述的内容。这个接口的名字叫ILocalObject,它有一个方法的声明叫localCall。注意localCall只是一个声明,它没有显示它将会如何实现localCall这个操作。
      package com.ztesoft.provisioning.local;
      
      /**
       * 本地调用接口
       * @author Lethorld
       *
       */
      public interface ILocalObject {
      	/**
      	 * 本地调用,用于测试
      	 * @param arg 入参
      	 * @return 返回
      	 */
      	public String localCall(String arg);
      }
      然后我们定义一个类LocalObjectImpl,该类实现了接口ILocalObject。方法localCall和2.1中介绍的完全一样。
      1. package com.ztesoft.provisioning.local.impl;
      2. import com.ztesoft.provisioning.local.ILocalObject;
      3. /**
      4. * 接口的实现类
      5. * @author Lethorld
      6. *
      7. */
      8. public class LocalObjectImpl implements ILocalObject {
      9. public String localCall(String arg) {
      10. // TODO : do something.
      11. return arg;
      12. }
      13. }
      package com.ztesoft.provisioning.local.impl;
      
      import com.ztesoft.provisioning.local.ILocalObject;
      
      /**
       * 接口的实现类
       * @author Lethorld
       *
       */
      public class LocalObjectImpl implements ILocalObject {
      	public String localCall(String arg) {
      		// TODO : do something.
      		return arg;
      	}
      }
      现在我们要改一下我们的主函数,用接口的方式完成对方法的调用。下面代码的17行,我们定义了一个接口对象object,它指向一个实现了该接口的类LocalObjectImpl的实例。
        package com.ztesoft.provisioning.local;
        
        import com.ztesoft.provisioning.local.impl.LocalObjectImpl;
        
        /**
         * 本地调用者
         * @author Lethorld
         *
         */
        public class LocalInvoker {
        	/**
        	 * 主函数
        	 * @param args 入参
        	 */
        	public static void main(String[] args) {
        		ILocalObject object = new LocalObjectImpl();
        		String retn = object.localCall("Hello");
        		System.out.println(retn);
        	}
        }

        2.3 万事俱备!让我们开始向RMI进发。

        有了2.1和2.2的铺垫,现在我们可以尝试写一个由JRMI实现的远程调用的程序了。
        首先,我们定义一个接口,该接口要继承自Remote接口。Remote接口在jdk中的解释为:“用于标识其方法可以从非本地虚拟机上调用的接口。”其实原理很简单,我们要使用远程调用的特性,那么注定我们的类和简单的本地类之间的处理是不完全一样的。比如说:怎么远程通信?怎么序列化(反序列化)入参、返回值?对于这些差异的处理,要么我们用户自己实现,要么丢给RMI,由RMI框架帮我们实现。当然,作为用户,我们不希望每次写个远程调用都去处理这些共性的东西。于是,RMI框架抽象出来一个Remote接口。这样,对于Java程序来说,凡是遇到继承自Remote的接口,Java编译器就知道这个类可能会被远程调用了。
        其二,所有的远程调用的接口的方法声明中,必须含有RemoteException的声明。从JDK文档中可以看出来,RemoteException是继承自IOException。这是什么意思呢?因为我们远程调用是通过网络实现的,所以对于服务器上的异常,客户端可以统一认为是IO读写异常。这也就不难理解为什么RemoteException会被定义成IOException的子类了。这里的处理个人理解可能有点泛化的意味在里面。远程调用,在服务器上(或者在通讯过程中)可能会发生异常的错误,这点所有人都可以保证。而反过来说,没有人可以保证远程调用,在服务器上(或者在通讯过程中)永远不发生错误。既然这样,那我们就规定:所有继承Remote的接口的方法声明中,必须含有RemoteException的声明。
        下面是一个继承自Remote接口的接口,接口取名为IRemoteTest。IRemoteTest内部有个remoteTest的方法的声明。这个方法接受一个String类型的入参,返回值的类型也是String的。同时,它需要申明可能抛出RemoteException异常。
          package com.ztesoft.provisioning.rmiserver;
          
          import java.rmi.Remote;
          import java.rmi.RemoteException;
          /**
           * 远程调用RMI,定义的接口
           * @author Lethorld
           * Remote 接口用于标识其方法可以从非本地虚拟机上调用的接口。
           * 任何远程对象都必须直接或间接实现此接口。只有在“远程接口”
           *(扩展 java.rmi.Remote 的接口)中指定的这些方法才可远程使用。 
           * 实现类可以实现任意数量的远程接口,并且可以扩展其他远程实现类。
           * RMI 提供一些远程对象实现可以扩展的有用类,这些类便于远程对象创建。
           * 这些类是 java.rmi.server.UnicastRemoteObject 
           * 和 java.rmi.activation.Activatable。
           */
          public interface IRemoteTest extends Remote{
          	public String remoteTest(String name) throws RemoteException;
          }
          
          接口定义好了,我们可以先把客户端的调用程序写完(接口存在的好处之一就是在不知道方法如何实现的前提下,我们同样可以完成对该方法调用的后续操作)。对于2.2中的调用,我们用一句
            ILocalObject object = new LocalObjectImpl();
            便可以实现创建一个LocalObjectImpl对象,并把这个对象赋给ILocalObject接口的任务。但是远程调用不行,因为你无法确切地知道远程服务器上的对象的名称(它并不是你本地的某个java类,它不受你的管束)。我们需要一个新的机制可以帮助我们获得远程对象的引用。这部分的工作有类Naming类实现。JDK中对该类的描述为:“Naming 类提供在对象注册表中存储和获得远程对远程对象引用的方法。”那么如何去定位一个远程对象呢?换句话说,我们如何唯一标识一个远程对象?让我们回到通常的WEB程序来看看究竟该如何处理。通常,我们要访问某一个网站,我们会在浏览器中输入网址。比如我们要访问csdn网站,我们可以输入http://www.csdn.net,点击确定,于是我们就可以浏览csdn的主页了。同样,我们还可以输入http://117.79.93.196来访问csdn主页。一般情况下,一个网站的地址会是这样的结构:http://ip:port。http://标志协议名,ip:port是典型的tcp地址。这样我们便能定位到某台机器上的某个特定的发布了的程序了。同理在浏览器中输入http://write.blog.csdn.net/postedit/7089374,你便会进入csdn博客的某篇文章(其实就是本文啦),也就是能访问到csdn网站的某个子资源。于是,我们可以认为,对于web应用http://ip:port/sub1/subsub1/...可以定位一个唯一的资源。对于RMI,其实貌似也是这么做的,只不过RMI不是HTTP,所以不用HTTP://开头;RMI貌似也不需要使用sub1/subsub1这样繁杂的子层嵌套结构。故同理:一个rmi://ip:port/name可以唯一定位一个RMI服务器上的发布了的对象。那么事实是不是这样呢?请看JDK关于Naming类的介绍,你会惊奇的发现,世界上的事,那都是想通的~
            那么,剩下的就太简单了:
            package test.com.ztesoft.zsmart.bss.provisioning.serviceActivation;
            
            import java.net.MalformedURLException;
            import java.rmi.Naming;
            import java.rmi.NotBoundException;
            import java.rmi.RemoteException;
            import com.ztesoft.provisioning.rmiserver.IRemoteTest;
            
            public class RmiSynCallTest {
            	public static void main(String[] args) throws RemoteException, MalformedURLException, NotBoundException {
            		String url = "rmi://localhost:9527/rmitest";
            		IRemoteTest test = (IRemoteTest)Naming.lookup(url);				
            		System.out.println(test.remoteTest("Lethorld"));
            	}
            }

            分享到:
            评论

            相关推荐

              Java RMI(Remote Method Invocation)远程方法调用 详解

              Remote Method Invocation是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法。 编写一个RMI的步骤 定义一个远程接口,此接口需要继承java.rmi.Remote 开发远程接口的实现类 创建...

              RMI.rar_Java RMI_java.rmi_java.rmi.Remot_remote

              Java RMI (Remote Method Invocation 远程方法调用)是用Java在JDK1.1中实现的,它大大增强了Java开发分布式应用的能力。

              RMI远程调用视频教材

              RMI是Remote Method Invocation(远程方法调用)的 所写。它允许一个Java程序调用网络中另一台计算机上的Java方法,就如调用本机的方法一样。实现RMI调用的程序和被调用的方法,都必须是Java代码,即客户端和服务器...

              Java中RMI远程调用

              Java远程方法调用,即Java RMI(Java Remote Method Invocation)是Java编程语言里,一种用于实现远程过程调用的应用程序编程接口。它使客户机上运行的程序可以调用远程服务器上的对象。远程方法调用特性使Java编程...

              java远程方法调用

              Java RMI(Remote Method Invocation,远程方法调用)是Java在JDK1.1及以后的版本中实现的,它能让一个Java程序调用网络中另外一台计算机上的Java方法,就如同调用本地方法一样。RMI大大增强了Java开发分布式应用的...

              Spring 实现远程访问详解——rmi

              1. 远程调用RMI(Remote Method Invocation): 通过使用 RmiProxyFactoryBean 和 RmiServiceExporter,并且,Spring支持两个传统的RMI(使用 java.rmi.Remote接口和java.rmi.RemoteException)和通过RMI调用器实现的...

              RMI.rar_remote_分布式 通信

              Java远程方法调用,即Java RMI(Java Remote Method Invocation)是Java编程语言里,一种用于实现远程过程调用的应用程序编程接口。它使客户机上运行的程序可以调用远程服务器上的对象。远程方法调用特性使Java编程...

              Java RMI远程方法调用详解

              RMI使用Java语言接口定义了远程对象,它集合了Java序列化和Java远程方法协议(Java Remote Method Protocol)。简单地说,这样使原先的程序在同一操作系统的方法调用,变成了不同操作系统之间程序的方法调用,由于...

              RMI入门教程

              RMI,远程方法调用(Remote Method Invocation)是Enterprise JavaBeans的支柱,是建立分布式Java应用程序的方便途径。RMI是非常容易使用的,但是它非常的强大。

              JavaBean和RMI 学习

              Java RMI(Remote Method Invocation)--Java的远程方法调用是Java所特有的分布式计算技术,它允许运行在一个Java虚拟机上的对象调用运行在另一个Java虚拟机上的对象的方法,从而使Java编程人员可以方便地在网络环境...

              java-RMI技术讲解.doc

              本文档主要讲述的是java_RMI技术讲解;RMI(Remote Method Invocation)为远程方法调用,是允许运行在一个Java虚拟机的对象调用运行在另一个Java虚拟机上的对象的方法。

              RMI(远程方法调用 )

              Remote Method Invocation ppt

              RMI 中文教程

              RMI,远程方法调用(Remote Method Invocation)是Enterprise JavaBeans的支柱,是建立分布式Java应用程序的方便途径。RMI是非常容易使用的,但是它非常的强大。

              学习笔记:JAVA RMI远程方法调用简单实例

               RMI(Remote Method Invocation)远程方法调用是一种计算机之间利用远程对象互相调用实现双方通讯的一种通讯机制。使用这种机制,某一台计算机上的对象可以调用另外一台计算机上的对象来获取远程数据。RMI是...

              RMI_Project

              Java RMI 指的是远程方法调用 (Remote Method Invocation)。它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法。可以用此方法调用的任何对象必须实现该远程接口。是网络分布于...

              Java学习之路-RMI学习

              Java远程方法调用,即Java RMI(Java Remote Method Invocation)是Java编程语言里,一种用于实现远程过程调用的应用程序编程接口。它使客户机上运行的程序可以调用远程服务器上的对象。远程方法调用特性使Java编程...

              基于Java RMI的分布式计算* (2005年)

              同时Java提供的远程方法调用(Remote Method Invocation, RMI)特性使客户机上运行的程序可以引用远程服务器上的远程对象方法,使得分布式计算更容易实现。详细地分析了Java RMI的工作原理,并结合实例分析表明该环境...

              RMI-master:第 1 部分 RMI

              Java RMI(Remote Method Invocation),是Java开发的一种调用远程方法的技术。 它为基于 Java 的分布式应用程序中的服务器和客户端的通信提供了一种简单的机制。 使用 RMI 构建分布式应用程序包括: 客户端上 ...

            Global site tag (gtag.js) - Google Analytics