RMI代表遠程方法調用,顧名思義,它是Java程序調用另一臺計算機上運行的對象的方法的協議。它提供了一個API(應用程序編程接口),用於從一個程序(稱為服務器)導出一個對象,並從另一個程序(稱為客戶機)調用該對象的方法,可能運行在不同的計算機上。
javarmi註冊表是javarmi系統的一個關鍵組件,它為服務器註冊服務和客戶機查找這些服務提供了一個集中的目錄。在本文中,我們將學習如何實現一個服務器來公開對象,以及如何實現一個客戶端來調用服務器上的方法,以及如何在RMI註冊表中註冊和查找服務。
為了瞭解javarmi系統如何工作的複雜性,讓我們實現一個簡單的服務器對象,提供一個接受名稱並返回問候語的方法。以下是對象接口的定義:
import java.rmi.Remote;import java.rmi.RemoteException;public interface Greeting extends Remote{ public String greet(String name) throws RemoteException;}接口的名稱稱為問候語。它提供了一個名為greet()的方法,它接受一個名稱並返回一個合適的問候語。
要將此接口標記為可導出,它需要擴展java.rmi.Remote文件接口。該方法還需要聲明一個throws子句列表java.rmi.RemoteException異常除了任何特定於應用程序的例外。這使得客戶機代碼可以處理(或傳播)遠程方法調用錯誤,例如找不到主機、連接失敗等。
聲明接口(客戶端使用)後,我們實現服務器端對象,並提供greet()方法,如圖所示。它使用一個簡單的格式字符串來格式化問候語。
public class GreetingObject implements Greeting{ private String fmtString = "Hello, %s"; public String greet(String name) { return String.format(this.fmtString, name); }}現在讓我們將所有這些部分整理在一起,並實現服務器的main()方法。讓我們來看看每一個相關的步驟。
完整的主方法。
import java.rmi.registry.LocateRegistry;import java.rmi.registry.Registry;import java.rmi.server.UnicastRemoteObject;public class Main{ static public void main(String[] args) throws Exception { if ( args.length == 0 ) { System.err.println("usage: java Main port#"); System.exit(1); } int index = 0; int port = Integer.parseInt(args[index++]); String name = "Greeting"; Greeting greeting = new GreetingObject(); Greeting stub = (Greeting)UnicastRemoteObject.exportObject(greeting, 0); Registry registry = LocateRegistry.getRegistry(port); registry.rebind(name, stub); System.out.println("Greeting bound to \"" + name + "\""); }}現在讓我們看看如何構建服務器。為了簡單起見,我們在Linux上使用命令行構建,而不是使用Maven之類的構建工具。
下面將源文件編譯為目標目錄中的類文件。
rm -rf targetmkdir targetjavac -d target src/server/*.java將類文件收集到JAR文件中執行。
jar cvf target/rmi-server.jar -C target server我們還收集將客戶機編譯為庫JAR所需的接口文件。
jar cvf target/rmi-lib.jar -C target server/Greeting.class現在讓我們來看看如何實現用於調用服務器對象方法的客戶機。
完整的客戶端代碼:
package client;import java.rmi.registry.LocateRegistry;import java.rmi.registry.Registry;import server.Greeting;public class Client{ static public void main(String[] args) throws Exception { if ( args.length != 3 ) { System.err.println("usage: java Client host port myName"); System.exit(1); } int index = 0; String host = args[index++]; int port = Integer.parseInt(args[index++]); String myName = args[index++]; String name = "Greeting"; Registry registry = LocateRegistry.getRegistry(host, port); Greeting greeting = (Greeting) registry.lookup(name); System.out.println(name + " reported: " + greeting.greet(myName)); }}現在讓我們運行服務器程序,以便它可以開始服務請求。
java -cp target/rmi-server.jar server.Main 1099# throwsException in thread "main" java.rmi.ConnectException: Connection refused to host: xxx; nested exception is: java.net.ConnectException: Connection refused這個例外是什麼?連接被拒絕。
出現此異常的原因是:請從服務器代碼中注意,它試圖連接到端口1099上的本地註冊表。如果失敗了,你會得到這個例外。
解決方案是運行RMI註冊表。RMI註冊表是Java虛擬機附帶的一個程序,稱為RMI註冊表。它應該位於Java虛擬機安裝的bin目錄中。運行它非常簡單:
/usr/lib/jvm/jdk1.8.0_71/bin/rmiregistry默認情況下,註冊表偵聽端口1099。要使其偵聽另一個端口,請按如下所示指定端口號:
/usr/lib/jvm/jdk1.8.0_71/bin/rmiregistry 1100使用netstat命令檢查指定端口上是否確實存在偵聽器:
netstat -an -t tcp -p | grep LISTEN...tcp6 0 0 :::1100 :::* LISTEN 23450/rmiregistry現在讓我們再次嘗試運行服務器。
java -cp target/rmi-server.jar server.Main 1100# throwsjava.rmi.UnmarshalException: error unmarshalling arguments...Caused by: java.lang.ClassNotFoundException: server.Greeting...又是個例外!這次是什麼?
服務器無法加載接口類服務器。問候語. 這是因為RMI註冊表無法加載所需的類。所以需要指定所需類的位置。一種方法是指定CLASSPATH環境變量:
CLASSPATH=../../junk/target/rmi-lib.jar /usr/lib/jvm/jdk1.8.0_71/bin/rmiregistry 1100嘗試再次運行服務器時,給出了以下內容:
java -cp target/rmi-server.jar server.Main 1100# printsGreeting bound to "Greeting"現在服務器正在運行。
在所有的部分都被組裝和執行之後,運行客戶機就很簡單了。它需要合適的罐子來執行。其中包括包含main()方法的類和接口類。它接受指示RMI註冊表運行位置的參數和問候語的名稱。
java -cp target/rmi-client.jar:target/rmi-lib.jar client.Client localhost 1100 Peter# printsGreeting reported: Hello, Peterjavarmi提供了一個API和工具來簡化遠程代碼的執行。您可以實現一個向javarmi註冊表註冊服務對象的服務器。客戶機可以查詢註冊表並獲取服務對象存根以調用服務方法。正如這個例子所說明的,這一切都非常簡單。
您在項目中使用javarmi嗎?你有什麼經歷?你有沒有別的選擇?請在下面的評論中告訴我們。
...本的互動是普通使用者請求它的一個頁面。例如,以這篇關於MakeUseOf的文章為例。它有一個URL,但在該位置的目錄中沒有實際的檔案。當讀者的瀏覽器請求一個URL時,web伺服器執行CMS的一個PHP檔案,例如索引.php檔案。 ...
... “我們把所有關於作曲家、藝術家和專輯的資訊放在樹的相關臂上。這是一種與流媒體提供商無關的方法。 ...
...在在哪裡)是一個旅行者的社交網路。無論你是想要一些關於廉價酒店的建議,需要了解外國城市的交通系統,還是隻想在度假時找個人一起去喝一杯,韋恩都能幫上忙。 ...
...s,然後彈出Aboutyou部分來驗證您的基本資訊。然後,去“關於你的寶寶”部分。 ...
... 無論你需要尿布的幫助,關於餵養和營養的細節,還是對孩子的發育有疑問,家長網送。您還可以註冊免費會員資格,以透過電子郵件接收獨家內容。他們提供了一些新聞稿供選擇,包括每日提示...
...計時事通訊、傳送到您收件箱的微型學習課程,以及10個關於各種主題的精彩時事通訊,所有這些都是非常好的建議,所以一定要檢視它們! ...
... 試著在網上找到關於這幢公寓樓的評論,看看是否有其他租客抱怨過。 詢問租賃公司或房東是否有臭蟲史。努力工作很重要。 ...
...現在你已經瞭解了TikTok的一些背景知識,是時候瞭解更多關於應用程式本身了。有了TikTok,你可以釋出15秒的古怪影片供整個繆斯社群觀看。您還可以選擇將這些影片連結到您的故事中,最長可持續60秒。 ...
... 這裡有關於所有連結的Apple裝置的資訊,包括名稱、時區和與該裝置關聯的最後註冊的IP地址。我還發現了一個包含蘋果零售店收據的資料夾,裡面有一張AppleCare維修的**,但沒有...