生活随笔
收集整理的這篇文章主要介紹了
ava RMI 框架(远程方法调用)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
2019獨角獸企業重金招聘Python工程師標準>>>
RMI(即Remote?Method?Invoke?遠程方法調用)。在Java中,只要一個類extends了java.rmi.Remote接口,即可成為存在于服務器端的遠程對象,供客戶端訪問并提供一定的服務。JavaDoc描述:Remote?接口用于標識其方法可以從非本地虛擬機上調用的接口。任何遠程對象都必須直接或間接實現此接口。只有在“遠程接口”(擴展?java.rmi.Remote?的接口)中指定的這些方法才可遠程使用。?
注意:extends了Remote接口的類或者其他接口中的方法若是聲明拋出了RemoteException異常,則表明該方法可被客戶端遠程訪問調用。?
同時,遠程對象必須實現java.rmi.server.UniCastRemoteObject類,這樣才能保證客戶端訪問獲得遠程對象時,該遠程對象將會把自身的一個拷貝以Socket的形式傳輸給客戶端,此時客戶端所獲得的這個拷貝稱為“存根”,而服務器端本身已存在的遠程對象則稱之為“骨架”。其實此時的存根是客戶端的一個代理,用于與服務器端的通信,而骨架也可認為是服務器端的一個代理,用于接收客戶端的請求之后調用遠程方法來響應客戶端的請求。?
RMI?框架的基本原理大概如下圖,應用了代理模式來封裝了本地存根與真實的遠程對象進行通信的細節。
下面給出一個簡單的RMI?應用,其中類圖如下:其中IService接口用于聲明服務器端必須提供的服務(即service()方法),ServiceImpl類是具體的服務實現類,而Server類是最終負責注冊服務器遠程對象,以便在服務器端存在骨架代理對象來對客戶端的請求提供處理和響應。
各個類的源代碼如下:
IService接口:
| ? import?java.rmi.Remote;? import?java.rmi.RemoteException;? public?interface?IService?extends?Remote {? ??//聲明服務器端必須提供的服務? ??String service(String content)?throws?RemoteException;? } |
ServiceImpl實現類:
| import?java.rmi.RemoteException;? //UnicastRemoteObject用于導出的遠程對象和獲得與該遠程對象通信的存根。? import?java.rmi.server.UnicastRemoteObject;?
public?class?ServiceImpl?extends?UnicastRemoteObject?implements?IService {?
??private?String name;?
??public?ServiceImpl(String name)?throws?RemoteException {? ????this.name = name;? ??}? ??@Override? ??public?String service(String content) {? ????return?"server >> "?+ content;? ??}? } |
Server類:
| /*? * Context接口表示一個命名上下文,它由一組名稱到對象的綁定組成。? * 它包含檢查和更新這些綁定的一些方法。? */? import?javax.naming.Context;? /*? * InitialContext類是執行命名操作的初始上下文。???? * 該初始上下文實現 Context 接口并提供解析名稱的起始點。? */? import?javax.naming.InitialContext;? public?class?Server {? ??public?static?void?main(String[] args) {? ????try?{? ??????//實例化實現了IService接口的遠程服務ServiceImpl對象? ??????IService service02 =?new?ServiceImpl("service02");? ??????//初始化命名空間? ??????Context namingContext =?new?InitialContext();? ??????//將名稱綁定到對象,即向命名空間注冊已經實例化的遠程服務對象? ??????namingContext.rebind("rmi://localhost/service02", service02);? ????}?catch?(Exception e) {? ??????e.printStackTrace();? ????}? ????System.out.println("服務器向命名表注冊了1個遠程服務對象!");? ??}? } |
Client類:
| import?javax.naming.Context;? import?javax.naming.InitialContext;?
public?class?Client {? ??public?static?void?main(String[] args) {? ????String url =?"rmi://localhost/";? ????try?{? ??????Context namingContext =?new?InitialContext();? ??????// 檢索指定的對象。 即找到服務器端相對應的服務對象存根? ??????IService service02 = (IService) namingContext.lookup(url? ??????????+?"service02");? ??????Class stubClass = service02.getClass();? ??????System.out.println(service02 +?" 是 "?+ stubClass.getName()? ??????????+?" 的實例!");? ??????// 獲得本底存根已實現的接口類型? ??????Class[] interfaces = stubClass.getInterfaces();? ??????for?(Class c : interfaces) {? ????????System.out.println("存根類實現了 "?+ c.getName() +?" 接口!");? ??????}? ??????System.out.println(service02.service("你好!"));? ????}?catch?(Exception e) {? ??????e.printStackTrace();? ????}? ??}? } |
將以上代碼保存于某一目錄下,先運行“start?rmiregistry”來啟動JDK自帶的注冊表程序,它用于保存Server類注冊的遠程對象并允許遠程客戶端的請求訪問;然后運行服務器端的Server類,即“start?java?Server”,該程序向注冊表中注冊具體的遠程對象;最后才是運行客戶端程序來查找并獲得服務器端的遠程對象存根,此時才能使用存根對象與服務器進行通信,命令是“java?Client”。注意:上面命令中的start的功能是重新打開一個DOS窗口。
運行結果如下:
?
其實整個簡單的RMI?應用中各個類的交互時序如下圖:
轉載于:https://my.oschina.net/chendongj/blog/898756
總結
以上是生活随笔為你收集整理的ava RMI 框架(远程方法调用)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。