Rmi学习笔记

简介:
RMI和RPC之间最主要的区别在于方法是如何别调用的。在RMI中,远程接口使每个远程方法都具有方法签名。如果一个方法在服务器上执行,但是没有相匹配的签名被添加到这个远程接口上,那么这个新方法就不能被RMI客户方所调用。在RPC中,当一个请求到达RPC服务器时,这个请求就包含了一个参数集和一个文本值,通常形成“classname.methodname”的形式。这就向RPC服务器表明,被请求的方法在为“classname”的类中,名叫“methodname”。然后RPC服务器就去搜索与之相匹配的类和方法,并把它作为那种方法参数类型的输入。这里的参数类型是与RPC请求中的类型是匹配的。一旦匹配成功,这个方法就被调用了,其结果被编码后返回客户方。
附英语描述(Difference between RMI and RPC):
RMI or Remote Method Invokation is very similar to RPC or Remote Proceedure call in that the client both send proxy objects (or stubs) to the server however the subtle difference is that client side RPC invokes FUNCTIONS through the proxy function and RMI invokes METHODS through the proxy function. RMI is considered slightly superior as it is an object-oriented version of RPC.
 
RMI 即远程方法调用(Remote Method Invocation)是Enterprise JavaBeans的支柱,是建立分布式Java应用程序的方便途径。
创建RMI 应用程序分四步:
(1) 定义和实现远端接口中的参数
(2)  定义和实现远端接口
(3)  编写服务端代码
(4)  编写客户端代码
(5)  启动rmiregistry ,  并将服务注册到rmiregistry.
JDK1.5 之后不再需要创建存根与基干,可以看到JAVA每天都在进步。
(1)定义和实现远端接口中的参数,这里定义一个学生实体,该类实现Serializable接口,因为参数可能需要网络传输.
package rmi; 

import java.io.Serializable; 

public  class Student  implements Serializable { 
   private  static  final  long serialVersionUID = 1L; 
   private String name; 
   private  int age; 
    
   public Student(String name,  int age) { 
     super(); 
     this.name = name; 
     this.age = age; 
  } 

   public String getName() { 
     return name; 
  } 

   public  void setName(String name) { 
     this.name = name; 
  } 

   public  int getAge() { 
     return age; 
  } 

   public  void setAge( int age) { 
     this.age = age; 
  } 

(2) 定义和实现远端接口
远端接口的定义如下,接口须从java.rmi.Remote继承;远端接口中的方法如果要throws异常,这个异常必须是java.rmi.RemoteException(或java.rmi.RemoteException的子类),否则,这个异常就不能被返回到客户端。
package rmi; 

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

public  interface InfoConsult  extends Remote{ 
         public  int getAge(String name)  throws RemoteException;    
         public Student getStudent(String name)  throws RemoteException;    
}
实现 远端接口
package rmi; 
import java.rmi.RemoteException; 
import java.rmi.server.UnicastRemoteObject; 
import java.util.List; 

public  class InfoConsultImpl  extends UnicastRemoteObject  implements InfoConsult{ 
         private List<Student> students; 
         protected InfoConsultImpl(List<Student> students)  throws RemoteException { 
              super(); 
                
              this.students = students; 

        } 
         public  int getAge(String name)  throws RemoteException{ 

              for(Student stu:students){ 

                      if(stu.getName().equals(name)){ 

                             return stu.getAge(); 
                     } 
             } 
              return -1; 
        } 

         public Student getStudent(String name)  throws RemoteException{ 

                 for(Student stu:students){ 

                         if(stu.getName().equals(name)){ 

                              return stu; 

                        } 
                } 
                 return  new Student( "null",-1); 
         } 

(3) 服务端代码,服务器端主要负责实现了一个远程的对象以提供服务。绑定名称给提供给远程的对象,并让运行中的系统可能开始了一个新的服务套接字或是共享一个服务套接字,监控远程方法调用的呼叫.
package rmi; 

import java.net.MalformedURLException; 
import java.rmi.Naming; 
import java.rmi.RemoteException; 
import java.rmi.registry.LocateRegistry; 
import java.rmi.server.UnicastRemoteObject; 
import java.util.ArrayList; 
import java.util.List; 

import javax.naming.Context; 
import javax.naming.InitialContext; 
import javax.naming.NamingException; 

public  class InfoServer { 

   public  static  void main(String args[])  throws RemoteException, 
      MalformedURLException, NamingException { 
                 //使用程序创建RIM注册服务 
     //LocateRegistry.createRegistry(8888); 
    InfoServer server =  new InfoServer(); 
    InfoConsult consult =  new InfoConsultImpl(server.getMockData()); 
     //consult= (InfoConsult)UnicastRemoteObject.exportObject(consult, 0); 
    Naming.rebind( "rmi://localhost:8888/InfoConsult", consult); 
     
  } 

  public List<Student> getMockData() { 

    List<Student> lst = new ArrayList<Student>(); 

    lst.add(new Student("guo", 26)); 

    lst.add(new Student("zhang", 24)); 

    lst.add(new Student("baby", 1)); 

    return lst; 

  } 

}
(4)客户端代码
package rmi; 

import java.net.MalformedURLException; 

import java.rmi.Naming; 

import java.rmi.NotBoundException; 

import java.rmi.RemoteException; 

public  class School { 
   public  static  void main(String args[]) { 

     try { 

      InfoConsult consult = (InfoConsult) Naming 
          .lookup( "rmi://localhost:8888/InfoConsult"); 
      System.out.println(consult.getStudent("baby").getAge()); 

    } catch (MalformedURLException e) { 

      e.printStackTrace(); 

    } catch (RemoteException e) { 

      e.printStackTrace(); 

    } catch (NotBoundException e) { 

      e.printStackTrace(); 

    } 
  } 

}
lookup获得远程对像,其实是代理. 调用远程方法.
(5)要启动服务端,务必先启RMI运行时. 用法很简单 RmiRegistry 8888.如果省去8888,默认1089.Java RMI 注册表只是一个允许客户端获得远程对象桩引用的简单名字服务.
有时执行这一步之后,启动服务端报以下错误:
1. java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:   
3... ..
没有找到存根类.InfoConsultImpl与其存根在同一目录下,为什么没有加载成功呢. 这是
因为存根类是由RmiRegistry 加载.而启动RmiRegistry 与启动服务端的classpath并不相同.所以就出现该异常.解决方法是先设定classpath环境变量这服务端工作目录,再启动服务端即可。
补充: 这一步也可以在程序里完成, JAVA提供了LocateRegistry.createRegistry(8888)方法创建服务.
(6)最后一步 启动服务端,启动客户端.显示结果1.

本文转自 anranran 51CTO博客,原文链接:http://blog.51cto.com/guojuanjun/269346
相关文章
|
2月前
|
存储 API 数据中心
docker的底层原理
本文概述了Docker的底层原理,包括客户端-服务器架构、容器运行时环境、内核共享、资源隔离、控制组、联合文件系统、可移植性、镜像构建以及插件和API等方面。
36 4
|
2月前
|
Linux 调度 数据安全/隐私保护
docker的底层原理五: 控制组
本文介绍了Docker中控制组(cgroups)的功能,包括CPU和内存控制、磁盘I/O和网络带宽限制、设备访问控制、审计和报告,以及层次化控制结构,确保容器资源使用的隔离性和限制性。
23 0
|
7月前
|
Ubuntu Linux iOS开发
docker简单使用1,OMG,学它
docker简单使用1,OMG,学它
|
7月前
|
Java Linux 虚拟化
浅谈Docker底层原理
浅谈Docker底层原理
80 0
|
API 数据中心 Docker
Docker的基本组成是什么?底层原理是什么?
Docker的基本组成是什么?底层原理是什么?
117 0
|
Linux 虚拟化 Docker
Docker是干什么的?底层原理是什么?
Docker是干什么的?底层原理是什么?
145 0
|
监控 安全 Java
RMI 的介绍和应用实例 | 学习笔记
快速学习 RMI 的介绍和应用实例
RMI 的介绍和应用实例 | 学习笔记
|
关系型数据库 MySQL 应用服务中间件
Docker(20)- docker rmi 命令详解
Docker(20)- docker rmi 命令详解
221 0
|
关系型数据库 MySQL Java
工具类—docker-compose使用
1.安装 docker-compose
145 0
|
Dubbo Java 应用服务中间件