`

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"));
            	}
            }

            分享到:
            评论

            相关推荐

              RMI代码 remote method invocation

              远程方法调用(Remote Method Invocation,RMI)是Java平台中一种用于分布式计算的技术,它允许Java对象在不同的 JVM(Java虚拟机)之间调用方法,仿佛这些对象都在同一个JVM中一样。RMI是Java EE(现在被称为...

              三种方式实现java远程调用(rmi),绝对可用

              Java远程调用(Remote Method Invocation,RMI)是Java平台中一种重要的分布式计算技术,它允许在不同网络环境中的Java对象之间进行透明的交互。在本文中,我们将深入探讨三种不同的RMI实现方法:原始方式、Spring...

              java远程调用rmi实例

              Java RMI(Remote Method Invocation)是Java平台提供的一种用于实现远程对象交互的技术。它允许一个Java对象调用另一个在不同 JVM(Java Virtual Machine)中的对象的方法,仿佛它们是在同一个进程中运行一样。本...

              JAVA远程调用RMI与应用

              JAVA远程调用RMI与应用 一、RMI(Remote Method Invocation)概念解析 RMI,即远程方法调用,是Java平台提供的分布式计算模型,它允许Java对象跨网络进行方法调用,如同本地调用一样。RMI的实现基于Java的面向对象...

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

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

              Remote Method Invocation-远程方法调用

              ### Remote Method Invocation (RMI) – 远程方法调用详解 #### 一、RMI 概述 **远程方法调用**(Remote Method Invocation, RMI)是Java平台中的一个核心概念和技术,它允许开发者创建分布式应用,在这些应用中,...

              java 远程调用rmi实现的简单例子

              Java RMI(Remote Method Invocation,远程方法调用)是Java平台提供的一种用于在不同网络节点上的Java对象之间进行通信的技术。这个技术允许一个Java对象在一台机器上执行方法,而这个方法的实现实际上位于另一台...

              java 远程方法调用(java rmi)

              Java 远程方法调用(Java RMI,Remote Method Invocation)是Java平台提供的一种用于构建分布式应用程序的技术。它允许一个对象在某个Java虚拟机(JVM)上执行的方法调用另一个在不同JVM上的对象的方法,仿佛它们是...

              JDK9-JSE- Java Remote Method Invocation API Guide-2.pdf

              Java Remote Method Invocation(Java RMI)是一种允许开发者创建分布式应用程序的技术。Java RMI 允许对象在另一个 Java 虚拟机(JVM)上调用远程 Java 对象的方法,可能在不同的主机上。Java RMI 使用对象序列化来...

              Java-远程方法调用RMI参数详解.docx

              Java 远程方法调用(Remote Method Invocation,RMI)是一种在分布式环境中调用对象方法的技术,它使得Java应用程序能够透明地调用运行在不同 JVM 上的远程对象的方法。RMI 包含了一系列的参数,这些参数对于优化...

              java调用RMI小结

              RMI(Remote Method Invocation,远程方法调用)是Java平台中用于分布式计算的一种技术,它允许一个Java对象调用另一个在不同 JVM(Java虚拟机)上的对象的方法,从而实现跨网络的通信。Java RMI 提供了一种透明的...

              JDK10-JSE,Java Remote Method Invocation API Guide-2.pdf

              Java Remote Method Invocation(Java RMI)是一种允许分布式应用程序在Java平台上运行的技术。它允许在不同的Java虚拟机(JVM)上运行的对象之间调用方法,从而实现分布式计算和信息-sharing。 Java RMI使用对象...

              JAVA RMI远程调用方法代码

              Java Remote Method Invocation (RMI) 是Java平台提供的一种用于创建分布式应用程序的技术,它允许对象在不同的JVM(Java虚拟机)之间通过网络进行方法调用。RMI的主要优点是其透明性,即开发者可以像调用本地方法...

              基于动态代理的Java远程调用框架的研究1

              本文探讨的是一种基于动态代理的Java远程调用框架,旨在解决传统远程调用技术如RMI(Remote Method Invocation)所面临的挑战。 RMI是Java平台上的基础远程调用技术,自JDK 1.1开始引入。它允许对象方法在不同的JVM...

              java rmi远程方法调用 客户端

              Java RMI(Remote Method Invocation,远程方法调用)是Java平台提供的一种分布式计算技术,它允许在不同的Java虚拟机之间透明地调用对象的方法。在RMI架构中,客户端能够像调用本地对象一样调用远程服务器上的对象...

              jdk20-java-remote-method-invocation-api-guide.pdf

              Java Platform, Standard Edition 的 Java Remote Method Invocation API Guide 介绍了 Java Remote Method Invocation(Java RMI)的概念和应用。Java RMI 是一种分布式应用程序开发技术,允许对象在不同的 Java ...

              通过Java RMI实现远程调用的一个简单例子

              Java RMI(Remote Method Invocation,远程方法调用)是Java平台提供的一种用于分布式计算的技术,它允许一个Java对象调用另一个在不同JVM上的对象的方法。这个简单的例子将引导我们了解如何利用Java RMI实现远程...

              java远程调用方法总结

              Java远程方法调用(Remote Method Invocation,简称RMI)是Java平台中用于分布式计算的核心技术。它允许一个Java对象在一台机器上调用另一台机器上的对象的方法,仿佛这些方法是在本地对象上调用一样。本篇文章将对...

              RMI实现的远程调用

              Java RMI(Remote Method Invocation,远程方法调用)是Java平台提供的一种用于在不同Java虚拟机之间进行远程通信的技术。通过RMI,开发者可以透明地调用运行在其他网络节点上的对象的方法,就像它们是在本地一样。...

            Global site tag (gtag.js) - Google Analytics