它是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