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每日一题】— —第二十二题:类名作参数进行方法调用的传递问题。
【Java每日一题】— —第二十二题:类名作参数进行方法调用的传递问题。
|
存储 Java
【Java基础】- RMI原理和使用详解
【Java基础】- RMI原理和使用详解
332 0
|
21天前
|
安全 Java
Java中WAIT和NOTIFY方法调用时机的深层解析
在Java多线程编程中,`wait()`和`notify()`方法的正确使用对于线程间的协调至关重要。这两个方法必须在同步块或同步方法中调用,这一规定的深层原因是什么呢?本文将深入探讨这一机制。
33 5
|
7月前
|
设计模式 Java 容器
【设计模式】JAVA Design Patterns——Async Method Invocation(异步方法调用模式)
【设计模式】JAVA Design Patterns——Async Method Invocation(异步方法调用模式)
|
6月前
|
Arthas 监控 Java
Java项目方法调用链路耗时追踪(接口优化)
Java项目方法调用链路耗时追踪(接口优化)
262 0
|
7月前
|
Java 索引
深入浅出JVM(五)之Java中方法调用
深入浅出JVM(五)之Java中方法调用
|
7月前
|
Java
【JAVA杂货铺】一文带你走进面向对象编程|构造方法调用 | 代码块分类| 期末复习系列 | (中3)
【JAVA杂货铺】一文带你走进面向对象编程|构造方法调用 | 代码块分类| 期末复习系列 | (中3)
37 0
|
Java 程序员
百度搜索:蓝易云【Java网络编程RMI框架详解。】
RMI框架提供了一种方便的方式来实现分布式系统中的远程通信和方法调用。它简化了网络编程的复杂性,使得开发人员可以专注于业务逻辑而不必过多关注底层网络细节。通过RMI框架,Java开发人员可以轻松构建可扩展、可靠的分布式应用程序。
54 2
|
Java
Java 实现汉字按照首字母分组排序
Java 实现汉字按照首字母分组排序
725 0
|
安全 Java
Java RMI 反序列化漏洞-远程命令执行
Java RMI 反序列化漏洞-远程命令执行
487 0