RMI 介紹
RMI (Remote Method Invocation) 模型是一種分布式對象應(yīng)用,使用 RMI 技術(shù)可以使一個 JVM 中的對象,調(diào)用另一個 JVM 中的對象方法并獲取調(diào)用結(jié)果。這里的另一個 JVM 可以在同一臺計算機也可以是遠程計算機。因此,RMI 意味著需要一個 Server 端和一個 Client 端。
Server 端通常會創(chuàng)建一個對象,并使之可以被遠程訪問。
這個對象被稱為遠程對象。Server 端需要注冊這個對象可以被 Client 遠程訪問。
Client 端調(diào)用可以被遠程訪問的對象上的方法,Client 端就可以和 Server 端進行通信并相互傳遞信息。
RMI 工作原理
正所謂 “知其然知其所以然”,在開始編寫 RMI 代碼之前,有必要了解一下 RMI 的工作原理,RMI 中 Client 端是和 Server 端是如何通信的呢?
下圖的可以幫助我們理解RMI 的工作流程。
從圖中可以看到,Client 端有一個被稱 Stub 的東西,有時也會被成為存根,它是 RMI Client 的代理對象,Stub 的主要功能是請求遠程方法時構(gòu)造一個信息塊,RMI 協(xié)議會把這個信息塊發(fā)送給 Server 端。
這個信息塊由幾個部分組成:
-
遠程對象標識符。
-
調(diào)用的方法描述。
-
編組后的參數(shù)值(RMI協(xié)議中使用的是對象序列化)。
既然 Client 端有一個 Stub 可以構(gòu)造信息塊發(fā)送給 Server 端,那么 Server 端必定會有一個接收這個信息快的對象,稱為 Skeleton 。
它主要的工作是:
-
解析信息快中的調(diào)用對象標識符和方法描述,在 Server 端調(diào)用具體的對象方法。
-
取得調(diào)用的返回值或者異常值。
-
把返回值進行編組,返回給客戶端 Stub.
到這里,一次從 Client 端對 Server 端的調(diào)用結(jié)果就可以獲取到了。
RMI 配置:
1.定義傳輸?shù)膶ο?,傳輸?shù)膶ο笮枰獙崿F(xiàn)序列化(Serializable)接口。
?public class Emp implements Serializable {
? ? ?private Integer empNo;
? ? ?private String empName;
? ? ?private String addr;
? ? ?
? ? ?//省略 get/set
? ? ?@Override
? ? ?public String toString() {
? ? ? ? ?return "Emp{" +
? ? ? ? ? ? ? ? ?"empNo=" + empNo +
? ? ? ? ? ? ? ? ?", empName='" + empName + '\'' +
? ? ? ? ? ? ? ? ?", addr='" + addr + '\'' +
? ? ? ? ? ? ? ? ?'}';
? ? }
?}
Server 端主要是構(gòu)建一個可以被傳輸?shù)念?User,一個可以被遠程訪問的類 UserService,同時這個對象要注冊到 RMI 開放給客戶端使用。
2.定義服務(wù)器接口(需要繼承 Remote 類,方法需要拋出 RemoteException)。
?public interface EmpService extends Remote {
? ? ?void addEmp(Emp emp) throws RemoteException;
? ? ?Emp findEmpById(Integer empNo) throws RemoteException;
??
?}
3.實現(xiàn)服務(wù)器接口(需要繼承 UnicastRemoteObject 類,實現(xiàn)定義的接口)。
?
public class EmpServiceImpl extends UnicastRemoteObject implements EmpService {
? ? ?public EmpServiceImpl() throws RemoteException {
? ? ? ? ?super();
??
? ? }
??
? ? ?@Override
? ? ?public void addEmp(Emp emp) throws RemoteException {
? ? ? ? ?System.out.println(emp);
? ? ? ? ?System.out.println("保存數(shù)據(jù)成功。");
??
? ? }
??
? ? ?@Override
? ? ?public Emp findEmpById(Integer empNo) throws RemoteException {
? ? ? ? ?System.out.println("id:" + empNo);
? ? ? ? ?System.out.println("查詢數(shù)據(jù)成功。");
? ? ? ? ?Emp emp = new Emp();
? ? ? ? ?emp.setEmpNo(empNo);
? ? ? ? ?emp.setEmpName("測試數(shù)據(jù)");
? ? ? ? ?emp.setAddr("測試數(shù)據(jù)");
? ? ? ? ?return emp;
??
? ? }
?}
4.注冊( rmiregistry)遠程對象,并啟動服務(wù)端程序。
服務(wù)端綁定了 UserService 對象作為遠程訪問的對象,啟動時端口設(shè)置為 2022。
?public class TestServer {
? ? ?public static void main(String[] args) throws Exception {
? ? ? ? ?EmpService imp = new EmpServiceImpl();
? ? ? ? ?//注冊遠程服務(wù)的端口
? ? ? ? ?LocateRegistry.createRegistry(2022);
? ? ? ? ?//將遠程服務(wù)對象綁定為遠程服務(wù)
? ? ? ? ?Naming.rebind("rmi://127.0.0.1:2022/a", imp);
? ? ? ? ?System.out.println("server啟動成功。。。");
??
??
? ? }
?}
RMI Client
相比 Server 端,Client 端就簡單的多。直接引入可遠程訪問和需要傳輸?shù)念?,通過端口和 Server 端綁定的地址,就可以發(fā)起一次調(diào)用。
?public class TestClient {
? ? ?public static void main(String[] args) throws Exception {
? ? ? ? ?EmpService server = (EmpService) Naming.lookup("rmi://127.0.0.1:2022/a");
? ? ? ? ?System.out.println("server:"+server);
? ? ? ? ?//遠程方法調(diào)用
? ? ? ? ?Emp emp = new Emp();
? ? ? ? ?emp.setAddr("tj");
? ? ? ? ?emp.setEmpName("喵星兔");
? ? ? ? ?emp.setEmpNo(2021);
? ? ? ? ?server.addEmp(emp);
??
? ? ? ? ?System.out.println(server.findEmpById(100));
??
? ? }
?}
RMI 測試
啟動 Server 端。
server啟動成功。。。文章來源:http://www.zghlxwxcb.cn/news/detail-789707.html
啟動 Client 端。
Emp{empNo=100, empName='測試數(shù)據(jù)', addr='測試數(shù)據(jù)'}文章來源地址http://www.zghlxwxcb.cn/news/detail-789707.html
到了這里,關(guān)于RMI簡介的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!