我們先來(lái)看看Java RMI的定義:
RMI(Remote Method Invocation,遠(yuǎn)端方法呼叫)是用Java在JDK1.2中實(shí)現(xiàn)的,它大大增強(qiáng)了Java開(kāi)發(fā)分散式應(yīng)用的能力。 Java作為一種風(fēng)靡一時(shí)的網(wǎng)頁(yè)開(kāi)發(fā)語(yǔ)言,其巨大的威力就體現(xiàn)在它強(qiáng)大的開(kāi)發(fā)分散式網(wǎng)路應(yīng)用的能力上,而RMI就是開(kāi)發(fā)百分之百純Java的網(wǎng)路分散式應(yīng)用系統(tǒng)的核心解決方案之一。其實(shí)它可以被看作是RPC的Java版本。但是傳統(tǒng)RPC並不能很好地應(yīng)用於分散式物件系統(tǒng)。而Java RMI 則支援儲(chǔ)存於不同位址空間的程式級(jí)物件之間彼此通信,實(shí)現(xiàn)遠(yuǎn)端物件之間的無(wú)縫遠(yuǎn)端呼叫。
RMI遠(yuǎn)端呼叫步驟
RMI的交互圖:
RMI由3個(gè)部分構(gòu)成,第一個(gè)是rmiregistry(JDK提供的一個(gè)可以獨(dú)立運(yùn)行的程序,在bin目錄下),第二個(gè)是server端的程序,對(duì)外提供遠(yuǎn)端對(duì)象,第三個(gè)是client端的程序,想要呼叫遠(yuǎn)端對(duì)象的方法。
首先,先啟動(dòng)rmiregistry服務(wù),啟動(dòng)時(shí)可以指定服務(wù)監(jiān)聽(tīng)的端口,也可以使用預(yù)設(shè)的端口(1099)。
其次,server端在本地先實(shí)例化一個(gè)提供服務(wù)的實(shí)現(xiàn)類,然後透過(guò)RMI提供的Naming/Context/Registry(下面實(shí)例用的Registry)等類的bind或rebind方法將剛才實(shí)例化好的實(shí)現(xiàn)類別註冊(cè)到rmiregistry上並對(duì)外暴露一個(gè)名稱。
最後,client端透過(guò)本地的介面和一個(gè)已知的名稱(即rmiregistry暴露出的名稱)再使用RMI提供的Naming/Context/Registry等類別的lookup方法從RMIService那拿到實(shí)作類別。這樣雖然本地沒(méi)有這個(gè)類別的實(shí)作類,但所有的方法都在介面裡了,便可以實(shí)現(xiàn)遠(yuǎn)端呼叫物件的方法了。
存根與骨幹網(wǎng)路的具體通訊過(guò)程:
#方法呼叫從客戶物件經(jīng)存根(stub)、遠(yuǎn)端引用層(Remote Reference Layer)和傳輸層(Transport Layer)向下,傳遞給主機(jī),然後再次經(jīng)由傳輸層,向上穿過(guò)遠(yuǎn)端呼叫層和骨幹網(wǎng)(Skeleton),到達(dá)伺服器物件。
存根扮演遠(yuǎn)端伺服器物件的代理程式的角色,使該物件可被客戶啟動(dòng)。
遠(yuǎn)端引用層處理語(yǔ)意、管理單一或多重物件的通信,決定呼叫是應(yīng)發(fā)送到一個(gè)伺服器還是多個(gè)。
傳輸層管理實(shí)際的連接,並且追蹤可以接受方法呼叫的遠(yuǎn)端物件。
骨幹網(wǎng)路完成對(duì)伺服器物件實(shí)際的方法調(diào)用,並取得返回值。
回傳值向下經(jīng)由遠(yuǎn)端引用層、伺服器端的傳輸層傳回客戶端,再向上經(jīng)傳輸層和遠(yuǎn)端呼叫層傳回。最後,存根獲得回傳值。
JAVA RMI簡(jiǎn)單範(fàn)例
本範(fàn)例是client端呼叫server端遠(yuǎn)端物件的加減法方法,具體步驟為:
1. 定義一個(gè)遠(yuǎn)端介面
import java.rmi.Remote; import java.rmi.RemoteException; /** * 必須繼承Remote接口。 * 所有參數(shù)和返回類型必須序列化(因?yàn)橐W(wǎng)絡(luò)傳輸)。 * 任意遠(yuǎn)程對(duì)象都必須實(shí)現(xiàn)此接口。 * 只有遠(yuǎn)程接口中指定的方法可以被調(diào)用。 */ public interface IRemoteMath extends Remote { // 所有方法必須拋出RemoteException public double add(double a, double b) throws RemoteException; public double subtract(double a, double b) throws RemoteException; }
(學(xué)習(xí)視訊分享:java視訊教學(xué))
2. 遠(yuǎn)端介面實(shí)作類別
import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; import remote.IRemoteMath; /** * 服務(wù)器端實(shí)現(xiàn)遠(yuǎn)程接口。 * 必須繼承UnicastRemoteObject,以允許JVM創(chuàng)建遠(yuǎn)程的存根/代理。 */ public class RemoteMath extends UnicastRemoteObject implements IRemoteMath { private int numberOfComputations; protected RemoteMath() throws RemoteException { numberOfComputations = 0; } @Override public double add(double a, double b) throws RemoteException { numberOfComputations++; System.out.println("Number of computations performed so far = " + numberOfComputations); return (a+b); } @Override public double subtract(double a, double b) throws RemoteException { numberOfComputations++; System.out.println("Number of computations performed so far = " + numberOfComputations); return (a-b); } }
3. 伺服器端
import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import remote.IRemoteMath; /** * 創(chuàng)建RemoteMath類的實(shí)例并在rmiregistry中注冊(cè)。 */ public class RMIServer { public static void main(String[] args) { try { // 注冊(cè)遠(yuǎn)程對(duì)象,向客戶端提供遠(yuǎn)程對(duì)象服務(wù)。 // 遠(yuǎn)程對(duì)象是在遠(yuǎn)程服務(wù)上創(chuàng)建的,你無(wú)法確切地知道遠(yuǎn)程服務(wù)器上的對(duì)象的名稱, // 但是,將遠(yuǎn)程對(duì)象注冊(cè)到RMI Registry之后, // 客戶端就可以通過(guò)RMI Registry請(qǐng)求到該遠(yuǎn)程服務(wù)對(duì)象的stub, // 利用stub代理就可以訪問(wèn)遠(yuǎn)程服務(wù)對(duì)象了。 IRemoteMath remoteMath = new RemoteMath(); LocateRegistry.createRegistry(1099); Registry registry = LocateRegistry.getRegistry(); registry.bind("Compute", remoteMath); System.out.println("Math server ready"); // 如果不想再讓該對(duì)象被繼續(xù)調(diào)用,使用下面一行 // UnicastRemoteObject.unexportObject(remoteMath, false); } catch (Exception e) { e.printStackTrace(); } } }
4. 客戶端
import java.rmi.registry.LocateRegistry; import java.rmi.registry.Registry; import remote.IRemoteMath; public class MathClient { public static void main(String[] args) { try { // 如果RMI Registry就在本地機(jī)器上,URL就是:rmi://localhost:1099/hello // 否則,URL就是:rmi://RMIService_IP:1099/hello Registry registry = LocateRegistry.getRegistry("localhost"); // 從Registry中檢索遠(yuǎn)程對(duì)象的存根/代理 IRemoteMath remoteMath = (IRemoteMath)registry.lookup("Compute"); // 調(diào)用遠(yuǎn)程對(duì)象的方法 double addResult = remoteMath.add(5.0, 3.0); System.out.println("5.0 + 3.0 = " + addResult); double subResult = remoteMath.subtract(5.0, 3.0); System.out.println("5.0 - 3.0 = " + subResult); }catch(Exception e) { e.printStackTrace(); } } }
結(jié)果如下:
server端
#client端
以上是Java RMI遠(yuǎn)端呼叫步驟分析的詳細(xì)內(nèi)容。更多資訊請(qǐng)關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

熱AI工具

Undress AI Tool
免費(fèi)脫衣圖片

Undresser.AI Undress
人工智慧驅(qū)動(dòng)的應(yīng)用程序,用於創(chuàng)建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費(fèi)的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費(fèi)的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強(qiáng)大的PHP整合開(kāi)發(fā)環(huán)境

Dreamweaver CS6
視覺(jué)化網(wǎng)頁(yè)開(kāi)發(fā)工具

SublimeText3 Mac版
神級(jí)程式碼編輯軟體(SublimeText3)
