1. 程式人生 > >Java遠端方法呼叫

Java遠端方法呼叫

一、入門篇

Java RMI指的是遠端方法呼叫(Remote Method Invocation). 它是一種機制, 能夠讓不同作業系統之間程式實現方法呼叫. 

比如: 一臺電腦上的Java程式可以通過RMI呼叫另一臺電腦上的方法(EJB底層就是使用RMI).

二、RMI和webservice

RMI是在TCP協議上傳遞可序列化的Java物件, 只能用在Java虛擬機器上, 客戶端和服務端必須都是Java.

webservice是在http協議上傳遞xml檔案, 它與語言和平臺無關, 可以在異構系統間傳遞.

對於不同語言間的通訊我們可以考慮用webservice或者公用物件請求代理體系COBRA來實現.


三、RMI的優點

RMI為分散式系統設計、程式設計帶來了遍歷. 只要按照RMI規則設計程式, 就不必過問網路細節, 如: TCP, Socket等.

任意兩臺計算機之間的通訊完全由RMI負責, 呼叫遠端計算機上的物件就像呼叫本地物件一樣方便.


四、例項篇

我們編寫這樣一個小程式: 客戶端傳遞兩個數字給伺服器端加法運算方法, 返回結果給客戶端.

1. 定義一個遠端介面類

/**
 * 定義一個遠端介面
 * @author zhangjim
 */
public interface ISumService extends Remote { // 必須繼承Remote介面
	
	// 需要遠端呼叫的方法必須丟擲RemoteException
	public int sum(int a, int b) throws RemoteException; 
	
}

遠端介面必須要繼承: java.rmi.Remote, 介面中的每一個方法必須丟擲遠端異常: java.rmi.RemoteException

為什麼要丟擲這個異常呢? 因為任何遠端方法呼叫實際上要進行許多低階網路操作, 而網路錯誤可能在呼叫過程中隨時發生.

因此, 所有RMI操作都應該放到try-catch塊中.

2. 定義一個實現遠端介面的類

/**
 * 遠端介面的實現類
 * @author zhangjim
 */
public class SumServiceImpl extends UnicastRemoteObject implements ISumService { // 必須從UnicastRemoteObject繼承 

	private static final long serialVersionUID = -3559316404683903070L;
	
	// 需要一個丟擲Remote異常的預設初始化方法 
	SumServiceImpl() throws RemoteException { 
		
	}
	
	// 業務方法, 傳入兩個數字, 返回相加結果
	public int sum(int a, int b) throws RemoteException {
		return a + b;
	}
}
UnicastRemoteObject: 讓客戶機與伺服器物件例項建立一對一的連線

3. 建立伺服器, 用於啟動RMI服務並繫結遠端物件

public class Server {
	public static void main(String[] args) {
		try {
			// 建立一個遠端物件 
			ISumService sumService = new SumServiceImpl();
			
			// 建立RMI登錄檔, 啟動RMI服務, 並指定埠為8888(Java預設埠是1099)
			// 這一步必不可少, 缺少登錄檔建立,則無法繫結物件到遠端登錄檔上 
			LocateRegistry.createRegistry(8888); 
			
			// 把遠端物件註冊到RMI註冊伺服器上,並命名為sum 
			// 繫結的URL標準格式為:rmi://host:port/name(其中協議名可以省略, 下面兩種寫法都是正確的)
			Naming.bind("rmi://localhost:8888/sum", sumService);
			// Naming.bind("//localhost:8888/sum", sumService);
			System.out.println("遠端物件繫結成功!");
		} catch (Exception e) {
			throw new RuntimeException("出錯了...", e);
		}
	}
}

也可以在命令列通過命令 rmiregistry 啟動註冊服務, 而且要事先用RMIC在bin目錄編譯SumServiceImpl類生成一個佔位程式(stub類)為它所用

4. 建立客戶端程式, 對RMI進行呼叫

/**
 * 客戶端測試,在客戶端呼叫遠端物件上的遠端方法,並返回結果
 * @author zhangjim
 */
public class Client {
	public static void main(String[] args) {
		try {
			// 在RMI服務登錄檔中查詢名稱為sum的物件
			ISumService sumService = (ISumService) Naming.lookup("rmi://localhost:8888/sum");
			
			// 呼叫相加方法
			System.out.println("相加結果為: " + sumService.sum(1, 2));
		} catch (Exception e) {
			throw new RuntimeException("出錯了...", e);
		}
	}
}

五、RMI的文章