Java远程方法调用RMI的实现

简介:
                                     RMI的实现
远程方法调用基本流程
      远程方法,可以让本地访问远程的对象。当需要访问远程对象的时候,一般需要在客户端或者客户堆中建立一些辅助对象,这些辅助对象使得客户感觉如同调用本地对象的方法一样。客户辅助对象乔装为服务对象,当客户调用客户辅助对象上的方法,客户辅助对象会联系服务器,传送方法调用信息(方法名称,变量等),然后就等待服务器的返回。
    在服务器端,服务辅助对象从客户辅助对象中接受请求(Socket连接),将调用的信息解包,然后调用服务器端上的真正服务对象的真正方法。对于服务对象来说,调用是本地的。
    服务辅助对象从服务中得到返回值,将它打包,然后就运回到客户辅助对象,客户辅助对象对信息解包,最后将返回值交给客户对象。

RMI概况
    RMI提供了客户辅助对象和服务辅助对象,为客户辅助对象和服务对象创建相同的方法。由于调用远程方法的过程中使用的是I/O和网络,而这些都有可能发生异常。
   RMI将客户辅助对象成为stub(桩),服务辅助对象称为skeleton(骨架)。

制作远程服务
    步骤一 制作远程接口:定义了可以供客户远程调用的方法。stub和实际服务都实现该接口
   步骤二 制作远程接口的实现:真正的实际工作的服务
   步骤三 利用rmic产生stub
   步骤四 启动RMI:registry,rmiregistry如同一个清单,客户可以从中查到代理的位置
   步骤五 开始启动远程服务:开始启动远程服务,一般服务实现类会去实例化一个服务实例,然后将这个服务注册到RMI registry。
   步骤一 制作远程接口
   一般首先扩展自Remote,Remote仅仅是一个记号接口,没有方法,在该接口中声明所有的方法都会抛出RemoteException,必须确定变量和返回值是原语性或者可序列化的,如果是复杂对象则需要对于负责对象先序列化。即让该复杂对象继承Serializable。
   步骤二 制作远程接口的实现
   具体的服务必须实现远程接口,同时一般直接扩展UnicastRemoteObject,设计一个不带变量的构造器,同时声明 RemoteException。(当类被实例化的时候,超类的构造器总是先被调用,如果超类的构造器抛出了异常,那么在子类的构造器中必须抛出异常,而 UnicastRemoteObject的构造器抛出了异常。)可以在实现类中注册该服务,但是必须要先启动 rmiregistry。 Naming.rebind("name",myremoteImpl)注册到 rmiregistry中。
   步骤三 产生stub
   rmic 远程实现类名
   步骤四 执行 rmiregistry
   步骤五 启动服务
   启动服务,一般可以在实现类的内部启动或者单独类中启动,主要就是注册到 rmiregistry
在远程虚拟机上启动服务器一般要包括两个服务器,一个是远程对象本身,还有一个是允许本地客户端下载远程对象引用的注册表。必须要先执行 rmiregistry目的开启注册表,然后再启动远程对象注册到该注册表中
  以上是服务器端的配置,在客户端,只需要该远程对象接口的类或者.class文件,以及利用rmic生成的stud文件。
代码实例
远程接口
import java.rmi.Remote;
import java.rmi.RemoteException;

public  interface MyRemote  extends Remote {
         public String sayHelloBaby()  throws RemoteException;
}
远程接口实现
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public  class MyRemoteImpl  extends UnicastRemoteObject  implements MyRemote {

   protected MyRemoteImpl()  throws RemoteException {
  }

  @Override
   public String sayHelloBaby()  throws RemoteException {
     // TODO Auto-generated method stub
     return  "Congratulations to you!";
  }
}
启动远程服务,必须先执行rmiregistry,
在windows下执行start  rmiregistry
import java.io.IOException;
import java.rmi.Naming;

public  class RMIServer {
   public  static  void main(String[] args) {
     // TODO Auto-generated method stub
                 try{
                  MyRemote f= new MyRemoteImpl();
                  Naming.rebind( "myfirst", f);
                  System.out.println( "OK");
                } catch(IOException e)
                {
                  System.err.println(e);
                }
  }
}

客户端服务
import java.rmi.Naming;
public  class MyRemoteClient {
     public  static  void main(String[] args) {
         // TODO Auto-generated method stub
          try
          {
               MyRemote service=(MyRemote)Naming.lookup( "rmi://127.0.0.1/FirstRemote");
               String res=service.sayHelloBaby();
               System.out.println("return="+res);
            }catch(Exception e)
             {
               e.printStackTrace();
           }
    }
}
整个目录截图如下
客户端所需要类:F:\JavaRMI\client
服务器所需要类:F:\JavaRMI\server
执行顺序是:
第一步:编译所有的类,在此要将远程对象接口复制到客户端下
第二步:执行rmic MyRemoteImpl,这个目的生成桩字节码
第三步:将该桩字节码复制一份到客户端目录下
第四步:启动rmiregistry服务,必须要保证桩字节码在classpath路径下
本次桩字节码在F:\JavaRMI\server,所以启动rmiregistry之前先设置路径
第五步:启动远程对象服务即RMIServer
第六步:执行客户端程序

在使用RMI的过程中,必须要注意:
1) 在启动远程服务之前先必须要启动rmiregistry,必须要保证桩在类路径中,
   可以在启动 rmiregistry之前设置
2)必须要让变量的返回值的类型成为可序列化的类型
3)客户端必须要有Stub类和远程对象接口类。

问题解决:
在执行服务器远程对象运行的中,可能会出现 java.rmi.ServerException: RemoteException occurred in server thread; nested  exception is:
这是因为 在执行start rmiregistry 命令前必须确保 MyRemoteImpl_Stub.class(留意包
名)包含在了CLASSPATH配置的路径中,所以必须在 在执行start rmiregistry命令前执行  
set CLASSPATH=%CLASSPATH%;F: \JavaRMI\server


本文转自 zhao_xiao_long 51CTO博客,原文链接:http://blog.51cto.com/computerdragon/1178053


相关文章
|
7月前
|
存储 Java
【Java基础】- RMI原理和使用详解
【Java基础】- RMI原理和使用详解
211 0
|
5月前
|
Java 程序员
百度搜索:蓝易云【Java网络编程RMI框架详解。】
RMI框架提供了一种方便的方式来实现分布式系统中的远程通信和方法调用。它简化了网络编程的复杂性,使得开发人员可以专注于业务逻辑而不必过多关注底层网络细节。通过RMI框架,Java开发人员可以轻松构建可扩展、可靠的分布式应用程序。
31 2
|
7月前
|
安全 Java
Java RMI 反序列化漏洞-远程命令执行
Java RMI 反序列化漏洞-远程命令执行
259 0
|
Java
Java 实现汉字按照首字母分组排序
Java 实现汉字按照首字母分组排序
556 0
|
10月前
|
存储 安全 网络协议
JAVA EE十三大规范(1)RMI(全网最深入浅出)
1.概述 RPC: RPC(Remote Procedure Call),一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议,RPC可以用HTTP协议实现,并且用HTTP是建立在 TCP 之上最广泛使用的 RPC,但是互联网公司往往用自己的私有协议,比如鹅厂的JCE协议,私有协议不具备通用性但是相比于HTTP协议,RPC采用二进制字节码传输,更加高效也更加安全。 用一个比较形象的例子来形容,你老婆出去打麻将,然后想起家里洗衣机里的衣服还没洗,于是打电话给在家里的你,叫你把洗衣机里的衣服洗了,这就是远程过程调用。微服务中服务的调用底层就是使用的RPC机制。
104 0
|
分布式计算 Java Hadoop
Java实现单词计数MapReduce
本文分享实现单词计数MapReduce的方法
301 0
|
Java 数据安全/隐私保护
JAVA 实现上传图片添加水印(详细版)(上)
JAVA 实现上传图片添加水印(详细版)
922 0
JAVA 实现上传图片添加水印(详细版)(上)
|
存储 Java
Java实现图书管理系统
本篇文章是对目前Java专栏已有内容的一个总结练习,希望各位小主们在学习完面向对象的知识后,可以阅览本篇文章后,自己也动手实现一个这样的demo来加深总结应用已经学到知识并进行巩固。
373 0
Java实现图书管理系统
|
Java Windows Spring
java实现spring boot项目启动时,重启Windows进程
java实现spring boot项目启动时,重启Windows进程
474 0