RMI(遠程接口調用)
1. RMI的原理:
RMI系統結構,在客戶端和服務器端都有幾層結構。
方法調用從客戶對象經佔位程序(Stub)、遠程引用層(Remote Reference Layer)和傳輸層(Transport Layer)向下,傳遞給主機,而後再次經傳 輸層,向上穿過遠程調用層和骨幹網(Skeleton),到達服務器對象。 佔位程序扮演着遠程服務器對象的代理的角色,使該對象可被客戶激活。 遠程引用層處理語義、管理單一或多重對象的通訊,決定調用是應發往一個服務器仍是多個。傳輸層管理實際的鏈接,而且追追蹤能夠接受方法調用的遠程對象。服務器端的骨幹網完成對服務器對象實際的方法調用,並獲取返回值。返回值向下經遠程引用層、服務器端的傳輸層傳遞迴客戶端,再向上經傳輸層和遠程調用層返回。最後,佔位程序得到返回值。
2. RMI(遠程方法調用)的組成
一個正常工做的RMI系統由下面幾個部分組成:
•遠程服務的接口定義
•遠程服務接口的具體實現
•樁(Stub)和框架(Skeleton)文件
•一個運行遠程服務的服務器
•一個RMI命名服務,它容許客戶端去發現這個遠程服務
•類文件的提供者(一個HTTP或者FTP服務器)
•一個須要這個遠程服務的客戶端程序 java
--------- ----------spring
| 客戶 | |服務器|服務器
---------- ----------框架
| |url
------------- ----------spa
-------------- -----------代理
| |code
------------------------------------
| 遠 程 引 用 層 |
------------------------------------
| |
------------------------------------
| 傳 輸 層 |
------------------------------------
方法調用從客戶對象經佔位程序(Stub)、遠程引用層(Remote Reference Layer)和傳輸層(Transport Layer)向下,傳遞給主機,而後再次經傳 輸層,向上穿過遠程調用層和骨幹網(Skeleton),到達服務器對象。 佔位程序扮演着遠程服務器對象的代理的角色,使該對象可被客戶激活。 遠程引用層處理語義、管理單一或多重對象的通訊,決定調用是應發往一個服務器仍是多個。傳輸層管理實際的鏈接,而且追追蹤能夠接受方法調用的遠程對象。服務器端的骨幹網完成對服務器對象實際的方法調用,並獲取返回值。返回值向下經遠程引用層、服務器端的傳輸層傳遞迴客戶端,再向上經傳輸層和遠程調用層返回。最後,佔位程序得到返回值。
要完成以上步驟須要有如下幾個步驟:
一、生成一個遠程接口
四、編寫服務器程序
五、編寫客戶程序
六、註冊遠程對象
七、啓動遠程對象
1、遠程接口:
import java.rmi.Remote; import java.rmi.RemoteException; public interface Ihello extends Remote{ public String sayHello(String name) throws RemoteException ; public String hello() throws RemoteException; }
實現類:
import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; import com.wa.spring.rmi.dao.Ihello; public class HelloImpl extends UnicastRemoteObject implements Ihello { public HelloImpl() throws RemoteException { super(); } public String sayHello(String name) throws RemoteException { return "hello, welcome "+name; } public String hello() throws RemoteException { return "good rmi"; } }
方法要拋出RemoteException不然出現如下異常:
2、實現遠程對象建立服務端程序:
import java.net.MalformedURLException; import java.rmi.AlreadyBoundException; import java.rmi.Naming; import java.rmi.RemoteException; import java.rmi.registry.LocateRegistry; import com.wa.spring.rmi.dao.Ihello; import com.wa.spring.rmi.dao.impl.HelloImpl; /** * * @author Administrator * 建立RMI註冊表,啓動RMI服務,並將遠程對象註冊到RMI註冊表中。 */ public class HelloServer { public static void main(String[] args) { try { //建立一個遠程對象 Ihello hello = new HelloImpl(); // //本地主機上的遠程對象註冊表Registry的實例,並指定端口爲8888, //這一步必不可少(Java默認端口是1099),必不可缺的一步,缺乏註冊表建立,則沒法綁定對象到遠程註冊表上 LocateRegistry.createRegistry(8888); //把遠程對象註冊到RMI註冊服務器上,並命名爲Hello //綁定的URL標準格式爲:rmi://host:port/name(其中協議名能夠省略,下面兩種寫法都是正確的) Naming.bind("rmi://localhost:8888/Hello",hello); // Naming.bind("//localhost:8888/RHello",rhello); System.out.println("====>>>url綁定成功"); } catch (RemoteException e) { System.out.println("建立遠程對象發生異常!"); e.printStackTrace(); } catch (MalformedURLException e) { System.out.println("url異常"); e.printStackTrace(); } catch (AlreadyBoundException e) { System.out.println("重複綁定異常"); e.printStackTrace(); } } }
3、建立客戶端程序:
import java.net.MalformedURLException; import java.rmi.Naming; import java.rmi.NotBoundException; import java.rmi.RemoteException; import com.wa.spring.rmi.dao.Ihello; /** * 在客戶端調用遠程對象上的遠程方法,並返回結果。 * @author Administrator * */ public class HelloClient { public static void main(String[] args) { try { //調用註冊的服務 Ihello hello = (Ihello) Naming.lookup("rmi://localhost:8888/Hello"); System.out.println(hello.hello()); System.out.println(hello.sayHello("納蘭容若")); } catch (MalformedURLException e) { e.printStackTrace(); } catch (RemoteException e) { e.printStackTrace(); } catch (NotBoundException e) { e.printStackTrace(); } } }
分別運行服務端和客戶端可看到輸出信息!
參考資料: