遠端方法呼叫——RMI
RMI
RMI (Remote Method Invocation)是Java用於實現透明遠端呼叫的重要機制。在遠端呼叫中,客戶端僅有伺服器端提供的介面 。通過此介面實現對遠端伺服器端的呼叫。其威力就體現在它強大的開發分散式網路應用的能力上,是純Java的網路分散式應用系統的核心解決方案之一。其實它可以被看作是RPC的Java版本。但是傳統RPC並不能很好地應用於分散式物件系統。而Java RMI 則支援儲存於不同地址空間的程式級物件之間彼此進行通訊,實現遠端物件之間的無縫遠端呼叫。
Sun JDK 6 .0 以前版本中的R M I 實現均是基於TCP/IP+BIO 方式的,RMI 伺服器端通過啟動RMI 註冊物件在一個埠上監聽對外提供的介面,其實現例項以字串的方式繫結到RMI 註冊物件上。RMI客戶端通過Proxy的方式代理了對伺服器端介面的訪問,RMI 客戶端將要訪問的伺服器端物件字串、方法和引數封裝成一個物件,序列化成流後通過TCP/IP + BIO 傳輸到 RMI 伺服器端。RMI 伺服器端接收到客戶端的請求物件後,解析其中的物件字串、方法及引數,通過物件字串從 RMI 註冊物件上找到提供業務功能的例項,之後結合要訪問的方法來反射獲取到方法例項物件,傳入引數完成對伺服器端物件例項的呼叫,返回的結果則序列化為流以 TCP/IP + BIO 方式返回給客戶端,客戶端在接收到此流後反序列化為物件,並返冋給呼叫者。
簡單例子
遠端呼叫介面:
/**
* 遠端介面<br/>
* 定義一個遠端介面,必須繼承Remote介面
*
* @author Joeson
* @since 07/2014
*/
public interface HelloRMI extends Remote
{
// 其中需要遠端呼叫的方法必須丟擲RemoteException異常
public String hello() throws RemoteException;
}
遠端呼叫介面實現:
/** * * 遠端呼叫實現類<br/> * 需要繼承UnicastRemoteObject類,同時因為UnicastRemoteObject的構造方法丟擲了RemoteException異常, * 因此這裡預設的構造方法必須寫,必須宣告丟擲RemoteException異常。 * * @author Joeson * @since 07/2014 * */ public class HelloRMIImpl extends UnicastRemoteObject implements HelloRMI { public HelloRMIImpl() throws RemoteException { super(); // TODO Auto-generated constructor stub } @Override public String hello() throws RemoteException { return "Hello, RMI"; } }
RMI伺服器端:
/** * RMI伺服器端<br/> * * * @author Joeson * @since 07/2014 * */ public class ServerRMI { public static void main(String[] args) { try { // 建立一個遠端物件 HelloRMI hello = new HelloRMIImpl(); // 本地主機上的遠端物件登錄檔Registry的例項,並指定埠為8080,這一步必不可少(Java預設埠是1099),必不可缺的一步,缺少登錄檔建立,則無法繫結物件到遠端登錄檔上 LocateRegistry.createRegistry(8080); // 把遠端物件註冊到RMI註冊伺服器上,並命名為Hello, 繫結的URL標準格式為:rmi://host:port/name Naming.bind("rmi://localhost:8080/Hello", hello); System.out.println("RMI服務啟動..."); } catch (RemoteException e) { System.out.println("建立遠端物件發生異常!"); } catch (AlreadyBoundException e) { System.out.println("發生重複繫結物件異常!"); e.printStackTrace(); } catch (MalformedURLException e) { System.out.println("發生URL畸形異常!"); e.printStackTrace(); } } }
RMI客戶端實現:
/**
* RMI客戶端<br/>
*
* @author Joeson
* @since 07/2014
*
*/
public class ClientRMI
{
public static void main(String args[])
{
try
{
// 在RMI服務登錄檔中查詢名稱為Hello的物件,並呼叫其上的方法
HelloRMI hello = (HelloRMI) Naming
.lookup("rmi://localhost:8080/Hello");
System.out.println(hello.hello());
} catch (NotBoundException e)
{
e.printStackTrace();
} catch (MalformedURLException e)
{
e.printStackTrace();
} catch (RemoteException e)
{
e.printStackTrace();
}
}
}
執行結果
以上就是一個客戶端通過RMI方式呼叫伺服器端的是實現,實現分散式系統呼叫,而RMI的底層的真正實現就在於反射機制、序列化、反序列化和Socket程式設計,客戶端並不需要提供具體的實現,而是通過介面的方式與伺服器端的具體實現進行互動,呼叫伺服器端具體的實現,實現客戶端想要的效果,這就是分散式系統的業務處理模型了