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: 
2  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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JavaEE学习笔记是我自己在学习过程中总结的javaweb各项技术和知识点。它包含了JavaEE的十三种核心技术,分别是JDBC、JNDI、EJB、RMI、Servlet、JSP、XML、JMS、Java IDL、JTS、JTA、JavaMail和JAF。 JavaEE是一个开放的标准的组件体系结构,它独立于平台,但使用Java语言。一个JavaBean是一个满足JavaBeans规范的Java类,通常定义了一个现实世界的事物或概念。一个JavaBean的主要特征包括属性、方法和事件。 在支持JavaBeans规范的开发环境中,可以可视地操作JavaBean,也可以使用JavaBean构造出新的JavaBean。JavaBean的优势还在于Java带来的可移植性。所以在JavaEE学习笔记中,你可以找到关于这些核心技术和JavaBean的详细内容和示例。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [javaEE学习笔记](https://download.csdn.net/download/sugar_map/10268742)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [JavaEE学习笔记整理](https://blog.csdn.net/qq_51861704/article/details/124133294)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值