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