RMI远程方法调用使用简介

1 RMI 主要构件:

服务器对象接口( server object interface ):是 java.rmi.Remote 接口的子接口,用来为服务器对象定义方法。

服务器的实现( server implementation ):是实现远程对象接口的一个类。

服务器对象( server object ):是服务器实现的一个实例。

RMI 注册处( RMI registry ):是注册远程对象并为本地对象提供命名服务的一个工具。

客户程序( client program ):是调用远程服务器对象的方法的一个程序。

服务器代理( server stub ):是位于客户主机的一个对象,其作用相当于远程服务器对象的一个代表。

服务器主架( server skeleton ):是位于服务器主机的一个对象,用于服务器代理与实际服务器对象的通信。

 

 

2 RMI 工作步骤:

a 、在 RMI 注册处注册一个服务器对象。

b 、客户从 RMI 注册处查找远程对象。

c 、一旦找到远程对象,就在客户中返回它的代理。

d 、远程对象可以像本地对象一样使用。客户和服务器之间的通信通过代理和主架处理。

 

JDK5 中,代理和主架可以自动生成。代理位于客户端主机,当客户调用服务器对象的一个方法时,实际调用的是封装在代理中的方法,代理再负责向服务器发送参数,接收来自服务器的结果并返回给客户。

而主架位于服务器端,与代理进行通信。接收来自客户的参数,把它们传输给服务器处理,并返回结果给代理。

 

在远程调用中,没有办法传递对象的引用,因为在一台机器上的地址对不同的 JVM 来说毫无意义。任何对象,只要它可以序列化,就可以用作远程调用的参数。代理将对象参数序列化、并发送到网络的流中,主架对流进行解读序列化,存到对象。

 

3 、客户是通过 RMI 注册处来定位远程对象的。 RMI 注册处为服务器注册对象以及为客户查找对象提供注册服务。 LocateRegistry 静态方法 getRegistry ()方法返回对 Registry 对象的引用。一旦获得 Registry 对象,就可以用 bindrebind 方法与注册处中的唯一名称绑定,或者使用 lookup 方法定位对象。

 

4 、开发 RMI 应用程序简单步骤:

  a 、定义服务器对象接口 : 必须是 java.rmi.Remote 接口的子接口,与 java.io.Serializable 一样, java.rmi.Remote 接口也是一个标记接口,不包含任何常数和方法,仅用来标记远程对象。

       public interface ServerInterface extends Remote {

       // 定义各种服务器端的方法

              public void service() throws RemoteException;// 必须抛出的异常

       }

  b 、定义服务器实现类:必须扩展 java.rmi.server.UnicastRemoteObject ,现实前面的接口。

       public class ServerInterfaceImpl extends UnicastRemoteObject

       implements ServerInterface {

              // 实现服务器对象接口的各种方法

              public void service () throws RemoteException {

                     ..........

              }

       }

  c 、在某个类中创建并注册服务器对象:由服务器实现类创建一个服务器对象,并注册到注册处

       ......

       ServerInterface server = new ServerInterfaceImpl();// 创建一个服务器对象

       Registry registry = LocateRegistry.getRegistry();// 得到注册处的引用

       registery.rebind(" 自定义的唯一的一个远程对象名称 ", server);// 注册对象

       ......

  d 、开发客户程序:一个查找远程对象并调用其方法的客户程序

       .........

       Registry registry = LocateRegistry.getRegistry(host);//host: 服务器的主机地址

       ServerInterface server =

(ServerInterfaceImpl) registry.lookup(" 服务端自定义的唯一的一个远程对象名称 ");

       server.service();// 就可以像本地对象一样使用服务端对象了。

       .........

 

5 、编译使用 RMI

    a 、启动注册处。在 DOS 中输入“ start rmiregistry 端口号”(端口号缺省)。

   b 、启动服务器对象程序。

   c 、启动客户端程序。

注:必须从 RMI 服务器的目录启动 rmiregistry ,否则有 ClassNotFoundException

    服务器、注册处、客户端可以处于三台不同机器,但需要将服务器对象接口分别放置在两台机器上。 如果是客户端是 applet ,则要将所有的客户端文件放置在注册处主机。

 

6 、完整实例:

 

Java代码
  1. package  rmi;  
  2. import  java.rmi.Remote;  
  3. import  java.rmi.RemoteException;  
  4. /**  
  5.  *从RMI服务器读取学生分数的服务器对象接口  
  6.  * @author Administrator  
  7.  */   
  8. public   interface  StudentServerInterface  extends  Remote{  
  9.      /**  
  10.       * return the score for the specified name  
  11.       * @param name the student name  
  12.       * @return an double score or -1 if the student is not found  
  13.       */   
  14.       public   double  findScore(String name)  throws  RemoteException;  
  15. }  
  16.    
package rmi;
import java.rmi.Remote;
import java.rmi.RemoteException;
/**
 *从RMI服务器读取学生分数的服务器对象接口
 * @author Administrator
 */
public interface StudentServerInterface extends Remote{
     /**
      * return the score for the specified name
      * @param name the student name
      * @return an double score or -1 if the student is not found
      */
      public double findScore(String name) throws RemoteException;
}
 
 

 

 

Java代码
  1. package  rmi;  
  2. import  java.util.HashMap;  
  3. import  java.rmi.RemoteException;  
  4. import  java.rmi.server.UnicastRemoteObject;  
  5. /**  
  6.  *RMI对象的服务器实现类  
  7.  * @author Administrator  
  8.  */   
  9. public   class  StudentServerInterfaceImpl  extends  UnicastRemoteObject  
  10. implements  StudentServerInterface{  
  11.     private  HashMap scores =  new  HashMap();  
  12.    
  13.     public  StudentServerInterfaceImpl()  throws  RemoteException{  
  14.         initializeStudent();  
  15.     }  
  16.     protected   void  initializeStudent(){  
  17.         scores.put("tufu"new  Double( 99.0 ));  
  18.         scores.put("tao"new  Double( 89.3 ));  
  19.         scores.put("bing"new  Double( 83.3 ));  
  20.     }  
  21.     /*Implement the findscore method from the student interface*/   
  22.     public   double  findScore(String name)  throws  RemoteException {  
  23.         Double d = (Double)scores.get(name);  
  24.         if (d ==  null ){  
  25.             System.out.println("Student " +name+ " is not found" );  
  26.             return  - 1 ;  
  27.         }  
  28.         else {  
  29.             System.out.println("Student " +name+ "\'s score is " +d.doubleValue());  
  30.             return  d.doubleValue();  
  31.         }  
  32.     }  
  33. }  
  34.    
package rmi;
import java.util.HashMap;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
/**
 *RMI对象的服务器实现类
 * @author Administrator
 */
public class StudentServerInterfaceImpl extends UnicastRemoteObject
implements StudentServerInterface{
    private HashMap scores = new HashMap();
 
    public StudentServerInterfaceImpl() throws RemoteException{
        initializeStudent();
    }
    protected void initializeStudent(){
        scores.put("tufu", new Double(99.0));
        scores.put("tao", new Double(89.3));
        scores.put("bing", new Double(83.3));
    }
    /*Implement the findscore method from the student interface*/
    public double findScore(String name) throws RemoteException {
        Double d = (Double)scores.get(name);
        if(d == null){
            System.out.println("Student "+name+" is not found");
            return -1;
        }
        else{
            System.out.println("Student "+name+"\'s score is "+d.doubleValue());
            return d.doubleValue();
        }
    }
}
 
 

 

 

 

 

Java代码
  1. package  rmi;  
  2. import  java.rmi.registry.Registry;  
  3. import  java.rmi.registry.LocateRegistry;  
  4. /**  
  5.  *从服务器实现类创建一个服务器对象,并在RMI服务器注册它  
  6.  * @author Administrator  
  7.  */   
  8. public   class  RegisterWithRMIServer {  
  9.     /*main method  
  10.       负责启动服务器*/   
  11.     public   static   void  main(String args[]){  
  12.         try {  
  13.             //创建服务器对象   
  14.             StudentServerInterface obj = new  StudentServerInterfaceImpl();  
  15.             //获得RMI注册处的引用   
  16.             Registry registry = LocateRegistry.getRegistry();  
  17.             //在注册处注册对象   
  18.             registry.rebind("StudentServerInterfaceImpl" , obj);  
  19.             System.out.println("Student server " +obj+ " registered" );  
  20.         }catch (Exception e){  
  21.             e.printStackTrace();  
  22.         }  
  23.     }  
  24. }  
  25.    
package rmi;
import java.rmi.registry.Registry;
import java.rmi.registry.LocateRegistry;
/**
 *从服务器实现类创建一个服务器对象,并在RMI服务器注册它
 * @author Administrator
 */
public class RegisterWithRMIServer {
    /*main method
      负责启动服务器*/
    public static void main(String args[]){
        try{
            //创建服务器对象
            StudentServerInterface obj = new StudentServerInterfaceImpl();
            //获得RMI注册处的引用
            Registry registry = LocateRegistry.getRegistry();
            //在注册处注册对象
            registry.rebind("StudentServerInterfaceImpl", obj);
            System.out.println("Student server "+obj+" registered");
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}
 
 

 

 

 

 

Java代码
  1. package  rmi.client;  
  2. import  java.rmi.registry.LocateRegistry;  
  3. import  java.rmi.registry.Registry;  
  4. import  javax.swing.*;  
  5. import  java.awt.*;  
  6. import  java.awt.event.*;  
  7. import  rmi.StudentServerInterface;  
  8. /**  
  9.  *创建一个RMI客户,用来调用RMI服务端的方法  
  10.  * @author Administrator  
  11.  */   
  12. public   class  StudentServerInterfaceClient  extends  JApplet{  
  13.     //Declare a student instance   
  14.     private  StudentServerInterface student;  
  15.    
  16.     private   boolean  isStandalone;  //Is applet or application   
  17.    
  18.     private  JButton jbtGetScore =  new  JButton( "Get Score" );  
  19.     private  JTextField jtfName =  new  JTextField();  
  20.     private  JTextField jtfScore =  new  JTextField();  
  21.    
  22.     public   void  init(){  //Applet的初始化方法   
  23.         initializeRMI(); //initial RMI   
  24.    
  25.         JPanel jPanel1 = new  JPanel();  
  26.         jPanel1.setLayout(new  GridLayout( 2 , 2 ));  
  27.         jPanel1.add(new  JLabel( "Name" ));  
  28.         jPanel1.add(jtfName);  
  29.         jPanel1.add(new  JLabel( "Score" ));  
  30.         jPanel1.add(jtfScore);  
  31.    
  32.         this .add(jbtGetScore,BorderLayout.SOUTH);  
  33.         this .add(jPanel1,BorderLayout.CENTER);  
  34.    
  35.         jbtGetScore.addActionListener(new  ActionListener(){  
  36.             public   void  actionPerformed(ActionEvent e){  
  37.                 getScore();  
  38.             }  
  39.         });  
  40.     }  
  41.    
  42.     private   void  initializeRMI(){  
  43.         String host = "" ;  
  44.         if (!isStandalone) host = getCodeBase().getHost();  //用Applet的方法获取调用该applet的主机   
  45.    
  46.         try {  
  47.             Registry registry = LocateRegistry.getRegistry(host);  
  48.             student = (StudentServerInterface)registry.lookup("StudentServerInterfaceImpl" );  
  49.             System.out.println("Server Object " +student+ " found" );  
  50.         }catch (Exception e){  
  51.             e.printStackTrace();  
  52.         }  
  53.     }  
  54.    
  55.     private   void  getScore(){  
  56.         try {  
  57.             double  score = student.findScore(jtfName.getText().trim());  
  58.             if (score <  0 )  
  59.                 jtfScore.setText("Not found" );  
  60.             else   
  61.                 jtfScore.setText(new  Double(score).toString());  
  62.         }catch (Exception e){  
  63.             e.printStackTrace();  
  64.         }  
  65.     }  
  66.    
  67.     /*Main method*/   
  68.     public   static   void  main(String args[]){  
  69.         StudentServerInterfaceClient applet =  
  70.                 new  StudentServerInterfaceClient();  
  71.         applet.isStandalone = true ;  
  72.         JFrame frame = new  JFrame();  
  73.         frame.setTitle("StudentServerInterfaceClient" );  
  74.         frame.add(applet,BorderLayout.CENTER);//fram可以嵌入applet   
  75.         frame.setSize(250 , 150 );  
  76.         applet.init();  
  77.         frame.setLocationRelativeTo(null );  
  78.         frame.setDefaultCloseOperation(3 );  
  79.         frame.show();  
  80.     }  
  81.    
  82. }  
package rmi.client;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import rmi.StudentServerInterface;
/**
 *创建一个RMI客户,用来调用RMI服务端的方法
 * @author Administrator
 */
public class StudentServerInterfaceClient extends JApplet{
    //Declare a student instance
    private StudentServerInterface student;
 
    private boolean isStandalone; //Is applet or application
 
    private JButton jbtGetScore = new JButton("Get Score");
    private JTextField jtfName = new JTextField();
    private JTextField jtfScore = new JTextField();
 
    public void init(){ //Applet的初始化方法
        initializeRMI(); //initial RMI
 
        JPanel jPanel1 = new JPanel();
        jPanel1.setLayout(new GridLayout(2,2));
        jPanel1.add(new JLabel("Name"));
        jPanel1.add(jtfName);
        jPanel1.add(new JLabel("Score"));
        jPanel1.add(jtfScore);
 
        this.add(jbtGetScore,BorderLayout.SOUTH);
        this.add(jPanel1,BorderLayout.CENTER);
 
        jbtGetScore.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
                getScore();
            }
        });
    }
 
    private void initializeRMI(){
        String host = "";
        if(!isStandalone) host = getCodeBase().getHost(); //用Applet的方法获取调用该applet的主机
 
        try{
            Registry registry = LocateRegistry.getRegistry(host);
            student = (StudentServerInterface)registry.lookup("StudentServerInterfaceImpl");
            System.out.println("Server Object "+student+" found");
        }catch(Exception e){
            e.printStackTrace();
        }
    }
 
    private void getScore(){
        try{
            double score = student.findScore(jtfName.getText().trim());
            if(score < 0)
                jtfScore.setText("Not found");
            else
                jtfScore.setText(new Double(score).toString());
        }catch(Exception e){
            e.printStackTrace();
        }
    }
 
    /*Main method*/
    public static void main(String args[]){
        StudentServerInterfaceClient applet =
                new StudentServerInterfaceClient();
        applet.isStandalone = true;
        JFrame frame = new JFrame();
        frame.setTitle("StudentServerInterfaceClient");
        frame.add(applet,BorderLayout.CENTER);//fram可以嵌入applet
        frame.setSize(250,150);
        applet.init();
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(3);
        frame.show();
    }
 
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值