你的位置:首页 > Java教程

[Java教程]Java远程方法调用(Remote Method Invocation,RMI)


Java RMI简介:

它是Java的一个核心API和类库,允许一个Java虚拟机上运行的Java程序调用不同虚拟机上运行的对象中的方法,即使这两个虚拟机运行于物理隔离的不同主机上。

Java RMI在JDK1.1版本已经存在,是非常重要的底层技术。

下面通过一个简单的例子来测试:

 1 package com.tc.remote; 2  3 import java.rmi.Remote; 4 import java.rmi.RemoteException; 5  6 /** 7  * 一个远程调用接口RMIQueryStatus 8  * 远程接口必须声明为public 9  * 远程接口必须继承自java.rmi.Remote10 */11 public interface RMIQueryStatus extends Remote{12 13   // 远程调用中的方法必须抛出RemoteException异常 14   RMIFileStatus getFileStatus(String filename) throws RemoteException;15 16 }

 1 package com.tc.remote; 2  3 import java.io.Serializable; 4  5 /** 6  * RMI文件状态类,远程调用方法返回的对象 7 */ 8 public class RMIFileStatus implements Serializable{ 9 10   private String filename;11 12   public RMIFileStatus() {13   }14 15   public RMIFileStatus(String filename) {16     this.filename = filename;17   }18 19   @Override20   public String toString() {21     return "RMIFileStatus{" +22         "filename='" + filename + '\'' +23         '}';24   }25 26 }

 1 package com.tc.remote; 2  3 import java.rmi.RemoteException; 4 import java.rmi.server.UnicastRemoteObject; 5  6 /** 7  * 远程接口的实现 . 8 */ 9 public class RMIQueryStatusImpl extends UnicastRemoteObject implements RMIQueryStatus {10 11   /**12    * 因为UnicastRemoteObject的构造函数抛出了RemoteException异常13    * 这里默认构造方法必须写14    * @throws RemoteException15   */16   public RMIQueryStatusImpl() throws RemoteException {17   }18 19   @Override20   public RMIFileStatus getFileStatus(String filename) throws RemoteException {21     RMIFileStatus status = new RMIFileStatus(filename);22     // ...进行处理23     return status;24   }25 26 }

 1 package com.tc.remote; 2  3 import java.net.MalformedURLException; 4 import java.rmi.Naming; 5 import java.rmi.RemoteException; 6 import java.rmi.registry.LocateRegistry; 7  8 /** 9  * 创建RMI注册表,启动RMI服务,并将远程对象注册到RMI注册表中。10 */11 public class RMIQueryStatusServer {12 13   public static String RMI_URL = "rmi://localhost:8888/RHello";14 15   public static void main(String[] args) {16     try {17       RMIQueryStatusImpl queryStatus = new RMIQueryStatusImpl();18       // 注册表创建19       LocateRegistry.createRegistry(8888);20       // 绑定远端对象到名字21       Naming.rebind(RMI_URL,queryStatus);22 //      Naming.bind(RMI_URL,queryStatus);23 //      bind方法在已经为一个名字绑定一个对象,再向此名称绑定对象,会抛出异常24 //      而使用rebind方法不会25       System.out.println(">>>>>INFO:远程RMIQueryStatus对象绑定成功!");26     } catch (RemoteException e) {27       e.printStackTrace();28     } catch (MalformedURLException e) {29       e.printStackTrace();30     }31   }32 33 }

 1 package com.tc.remote; 2  3 import java.net.MalformedURLException; 4 import java.rmi.Naming; 5 import java.rmi.NotBoundException; 6 import java.rmi.RemoteException; 7  8 /** 9  * 客户端测试,在客户端调用远程对象上的远程方法,并返回结果。10 */11 public class RMIQueryStatusClient {12 13   public static void main(String[] args) {14     try {15       RMIQueryStatus queryStatus = (RMIQueryStatus) Naming.lookup(RMIQueryStatusServer.RMI_URL);16       // 调用远程方法,该调用如同调用本地方法17       RMIFileStatus status = queryStatus.getFileStatus("爆炸");18       System.out.println(status);19     } catch (NotBoundException e) {20       e.printStackTrace();21     } catch (MalformedURLException e) {22       e.printStackTrace();23     } catch (RemoteException e) {24       e.printStackTrace();25     }26   }27 28 }

先运行RMIQueryStatusServer 的main方法:

注意:虽然main方法的执行很快,但是服务器还是会继续运行的,红色的方块表示了运行。

再运行RMIQueryStatusClient 的main方法:

这里只是简单的进行了测试,感觉Client需要拿到Server的RMI_URL,还是有比较强的依赖性。

希望实际项目中用到以后能够有更深刻的理解。

 

http://docs.oracle.com/javase/8/docs/technotes/guides/rmi/index.html