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.Remote 10 */ 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 @Override 20 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 RemoteException 15 */ 16 public RMIQueryStatusImpl() throws RemoteException { 17 } 18 19 @Override 20 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
欢迎关注云原生玩码部落(https://www.funnycode.org.cn)