Java RMI詳解
RMI:遠端方法呼叫(Remote Method Invocation)。能夠讓在某個java虛擬機器上的物件像呼叫本地物件一樣呼叫另一個java 虛擬機器中的物件上的方法。
RMI遠端呼叫步驟:
1,客戶物件呼叫客戶端輔助物件上的方法
2,客戶端輔助物件打包呼叫資訊(變數,方法名),通過網路傳送給服務端輔助物件
3,服務端輔助物件將客戶端輔助物件傳送來的資訊解包,找出真正被呼叫的方法以及該方法所在物件
4,呼叫真正服務物件上的真正方法,並將結果返回給服務端輔助物件
5,服務端輔助物件將結果打包,傳送給客戶端輔助物件
6,客戶端輔助物件將返回值解包,返回給客戶物件
7,客戶物件獲得返回值
對於客戶物件來說,步驟2-6是完全透明的
搭建一個RMI服務的過程分為以下7步;
1,建立遠端方法介面,該介面必須繼承自Remote介面
Remote 介面是一個標識介面,用於標識所包含的方法可以從非本地虛擬機器上呼叫的介面,Remote介面本身不包含任何方法
package server;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Hello extends Remote {
public String sayHello(String name) throws RemoteException;
}
由於遠端方法呼叫的本質依然是網路通訊,只不過隱藏了底層實現,網路通訊是經常會出現異常的,所以介面的所有方法都必須丟擲RemoteException
2,建立遠端方法介面實現類:
UnicastRemoteObject類的建構函式丟擲了RemoteException,故其繼承類不能使用預設建構函式,繼承類的建構函式必須也丟擲RemoteException
由於方法引數與返回值最終都將在網路上傳輸,故必須是可序列化的
package server; import java.rmi.RemoteException; import java.rmi.server.UnicastRemoteObject; public class HelloImpl extends UnicastRemoteObject implements Hello { private static final long serialVersionUID = -271947229644133464L; public HelloImpl() throws RemoteException{ super(); } public String sayHello(String name) throws RemoteException { return "Hello,"+name; } }
3,利用java自帶rmic工具生成sutb存根類(jdk1.5.0_15/bin/rmic)
jdk1.2以後的RMI可以通過反射API可以直接將請求傳送給真實類,所以不需要skeleton類了
sutb存根為遠端方法類在本地的代理,是在服務端程式碼的基礎上生成的,需要HelloImpl.class檔案,由於HelloImpl繼承了Hello介面,故Hello.class檔案也是不可少的
Test
- - server
- - - - Hello.class
- - - - HelloImpl.class
方式一:
[[email protected] Test]$ cd /home/name/Test/
[[email protected] Test]$ rmic server.HelloImpl
方式二:
[[email protected] Test]$ rmic -classpath /home/name/Test server.HelloImpl
執行成功後將會生成HelloImpl_Stub.class檔案
4,啟動RMI註冊服務(jdk1.5.0_15/bin/rmiregistry)
方式一:後臺啟動rmiregistry服務
[[email protected] jdk]$ jdk1.5.0_15/bin/rmiregistry 12312 &
[1] 22720
[[email protected] jdk]$ ps -ef|grep rmiregistry
name 22720 13763 0 16:43 pts/3 00:00:00 jdk1.5.0_15/bin/rmiregistry 12312
name 22737 13763 0 16:43 pts/3 00:00:00 grep rmiregistry
如果不帶具體埠號,則預設為1099
方式二:人工建立rmiregistry服務,需要在程式碼中新增:
LocateRegistry.createRegistry(12312);
5,編寫服務端程式碼
package server;
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
public class HelloServer {
public static void main(String[] args) {
try{
Hello h = new HelloImpl();
//建立並匯出接受指定port請求的本地主機上的Registry例項。
//LocateRegistry.createRegistry(12312);
/** Naming 類提供在物件登錄檔中儲存和獲得遠端對遠端物件引用的方法
* Naming 類的每個方法都可將某個名稱作為其一個引數,
* 該名稱是使用以下形式的 URL 格式(沒有 scheme 元件)的 java.lang.String:
* //host:port/name
* host:登錄檔所在的主機(遠端或本地),省略則預設為本地主機
* port:是登錄檔接受呼叫的埠號,省略則預設為1099,RMI登錄檔registry使用的著名埠
* name:是未經登錄檔解釋的簡單字串
*/
//Naming.bind("//host:port/name", h);
Naming.bind("rmi://192.168.58.164:12312/Hello", h);
System.out.println("HelloServer啟動成功");
}catch(Exception e){
e.printStackTrace();
}
}
}
先建立登錄檔,然後才能在登錄檔中儲存遠端物件資訊
6,執行服務端(58.164):
Test
- - server
- - - - Hello.class
- - - - HelloImpl.class
- - - - HelloServer.class
[[email protected] ~]$ java server.HelloServer
HelloServer啟動成功
當然/home/name/Test一定要在系統CLASSPATH中,否則會報找不到相應的.class檔案
7,編寫客戶端程式碼
package client;
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import server.Hello;
public class HelloClient {
public static void main(String[] args) {
try {
Hello h = (Hello)Naming.lookup("rmi://192.168.58.164:12312/Hello");
System.out.println(h.sayHello("zx"));
} catch (MalformedURLException e) {
System.out.println("url格式異常");
} catch (RemoteException e) {
System.out.println("建立物件異常");
e.printStackTrace();
} catch (NotBoundException e) {
System.out.println("物件未繫結");
}
}
}
8,執行客戶端(58.163):
Test
- - client
- - - - HelloClient.class
- - server
- - - - Hello.class
- - - - HelloImpl_Stub.class//服務端生成的存根檔案
[[email protected] client]$ java client.HelloClient
Hello,zx
同伺服器端,/home/name/Test一定要在系統CLASSPATH中
PS:
1,客戶端所在服務和服務端所在的伺服器網路一定要通(一開始浪費了很多時間,最後才發現是網路不通)
2,所有程式碼在jdk1.5.0_15,Linux伺服器上除錯通過
3,如果java命令執行提示找不到類檔案,則為CLASSPATH配置問題
[[email protected] ~]$ vi .bash_profile
JAVA_HOME=/home/name/jdk/jdk1.5.0_15
export JAVA_HOME
PATH=$JAVA_HOME/bin:$PATH
export PATH
CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:/home/name/Test
export CLASSPATH
JAVA_HOME為jdk的根目錄
PATH為java工具類路徑(java,javac,rmic等)
CLASSPATH為java .class檔案的存放路徑,使用java命令執行.class檔案時即會在該引數配置的路徑下尋找相應檔案
java RMI的缺點:
1,從程式碼中也可以看到,程式碼依賴於ip與埠
2,RMI依賴於Java遠端訊息交換協議JRMP(Java Remote Messaging Protocol),該協議為java定製,要求服務端與客戶端都為java編寫
相關推薦
布式架構基礎:Java RMI詳解
RMI簡介 Java RMI,即 遠端方法呼叫(Remote Method Invocation),一種用於實現遠端過程呼叫(RPC)(Remote procedure call)的Java API, 能直接傳輸序列化後的Java物件和分散式垃圾收集。它的
分散式架構基礎:Java RMI詳解
GitHub: github.com/jayknoxqu/r… RMI簡介 Java RMI,即 遠端方法呼叫(Remote Method Invocation),一種用於實現遠端過程呼叫(RPC)(Remote procedure call)的Java API, 能直接傳輸序列化後的Java物件和分
分散式架構基礎之Java RMI詳解
RMI簡介 Java RMI或遠端方法呼叫是用於遠端過程呼叫的Java API,它可以直接傳輸序列化Java物件和分散式垃圾收集。它的實現依賴於Java虛擬機器(JVM),因此它只支援從一個JVM到另一個JVM的呼叫。 rmi的實現 (1) 直接使用Regist
Java RMI詳解
RMI:遠端方法呼叫(Remote Method Invocation)。能夠讓在某個java虛擬機器上的物件像呼叫本地物件一樣呼叫另一個java 虛擬機器中的物件上的方法。 RMI遠端呼叫步驟: 1,客戶物件呼叫客戶端輔助物件上的方法 2,客戶端輔助物件打包呼叫資訊(變數
java final詳解
inline mon 技術 但是 common src strac 都是 機制 final關鍵字 可用於聲明屬性、方法、和類 final類: final 類 不可被繼承,沒有子類,包括其中的方法默認都是final方法; final 類的方法不可被重寫,但是其中沒有被f
Java IO詳解
amr mst 數據丟失 網上 ria break idc png 字符串 學習Java的同學註意了!!! 學習過程中遇到什麽問題或者想獲取學習資源的話,歡迎加入Java學習交流群,群號碼:618528494 我們一起學Java! 初學Java,一直搞不懂Java裏
Java synchronized詳解
ret 內置 etc 優先權 one lan string 作用域 靜態成員函數 轉自:http://www.cnblogs.com/devinzhang/archive/2011/12/14/2287675.html 第一篇: 使用synchronized 在編寫一個
Java 反射詳解
什麽 tco type 性能 bob 參數 bject 今天 erl 反射反射,程序員的快樂,今天你快樂了嗎?如果你不快樂,沒關系,接下來讓你快樂起來! 一、什麽是反射? 通過百度百科我們可以知道,Java反射就是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬
Java代理詳解
.get tle 理由 總結 ins 創建 set ota ble 一、概述 代理模式是Java常用的設計模式之一,實現代理模式要求代理類和委托類(被代理的類)具有相同的方法(提供相同的服務),代理類對象自身並不實現真正的核心邏輯,而是通過調用委托類對象的相關方法來處
spark2.x由淺入深深到底系列六之RDD java api詳解二
spark 大數據 javaapi 老湯 rdd package com.twq.javaapi.java7; import org.apache.spark.SparkConf; import org.apache.spark.api.java.JavaRDD; import org.
spark2.x由淺入深深到底系列六之RDD java api詳解三
老湯 spark 大數據 javaapi rdd 學習任何spark知識點之前請先正確理解spark,可以參考:正確理解spark本文詳細介紹了spark key-value類型的rdd java api一、key-value類型的RDD的創建方式1、sparkContext.parall
spark2.x由淺入深深到底系列六之RDD java api詳解四
spark 大數據 javaapi 老湯 rdd 學習spark任何的知識點之前,先對spark要有一個正確的理解,可以參考:正確理解spark本文對join相關的api做了一個解釋SparkConf conf = new SparkConf().setAppName("appName")
Java HashCode詳解
popu 容器類 itl 基本上 映射 nat 程序設計語言 http 容器 一、為什麽要有Hash算法 Java中的集合有兩類,一類是List,一類是Set。List內的元素是有序的,元素可以重復。Set元素無序,但元素不可重復。要想保證元素不重復,兩個元素是否重復應該依
Java異常詳解
ror 編寫 等於 title 操作系統 通過反射 異常類 原因 數組 一、Java異常概述 在Java中,所有的事件都能由類描述,Java中的異常就是由java.lang包下的異常類描述的。 Throwable(可拋出):異常類的最終父類,它有兩個子類,Error與Ex
Java BigDecimal詳解,提供了豐富的四舍五入規則
字節 equals mat hashcode 字符 plain move man gnu java.math.BigDecimal類提供用於算術,刻度操作,舍入,比較,哈希算法和格式轉換操作。 toString()方法提供BigDecimal的規範表示。它使用戶可以完全控制
Java:詳解內部類
進行 system 創建 經典 生成 接口 為什麽 bsp 產生 可以將一個類的定義放在另一個類的定義內部,這就是內部類。 內部類是一個非常有用的特性但又比較難理解使用的特性(鄙人到現在都沒有怎麽使用過內部類,對內部類也只是略知一二)。 第一次見面
【java】詳解JFrame結構的分層
運行 容器 ava 背景色 jpanel new ima () 詳解 在這篇博文中,筆者會介紹JFrame窗口的分層。JFrame繼承自Frame,同JFrame、JDialog、JApplet都是重量級組件。如果不弄清楚Frame的分層結構,那麽在設置組件的某些特效的時候
【Java】詳解菜單組件
組件 tcl 而是 ide 就會 npe awt div 鍵盤 在這篇文章中,筆者會介紹Java圖形界面編程中菜單組件的用法。關於菜單組件,因為java存在AWT編程和Swing編程,所以菜單組件也存在AWT菜單和Swing菜單。因為Swing組件使用的比較多,所以筆者的案
Java ClassLoad詳解
method oda tor tst 語言 不同版本 -i tla 情況下 Java ClassLoad詳解 類加載器是 Java 語言的一個創新,也是 Java 語言流行的重要原因之一。它使得 Java 類可以被動態加載到 Java 虛擬機中並執行。類加載
java反射詳解
編譯 imp 成員 參數類型 信息 執行方法 定義 所有 c++ 1.什麽是反射 反射是一種間接操作目標對象的機制,在程序程序運行時(動態)獲取或者設置對象自身的信息。只要給定類的名字,就可以通過反射獲取類的所有信息,接著便能調用它的任何一個方法和屬性。 Jav