自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Java 中 RMI 的使用

開(kāi)發(fā) 后端
RMI (Remote Method Invocation) 模型是一種分布式對(duì)象應(yīng)用,使用 RMI 技術(shù)可以使一個(gè) JVM 中的對(duì)象,調(diào)用另一個(gè) JVM 中的對(duì)象方法并獲取調(diào)用結(jié)果。這里的另一個(gè) JVM 可以在同一臺(tái)計(jì)算機(jī)也可以是遠(yuǎn)程計(jì)算機(jī)。

[[398352]]

本文轉(zhuǎn)載自微信公眾號(hào)「未讀代碼」,作者未讀君 。轉(zhuǎn)載本文請(qǐng)聯(lián)系未讀代碼公眾號(hào)。

RMI 介紹

RMI (Remote Method Invocation) 模型是一種分布式對(duì)象應(yīng)用,使用 RMI 技術(shù)可以使一個(gè) JVM 中的對(duì)象,調(diào)用另一個(gè) JVM 中的對(duì)象方法并獲取調(diào)用結(jié)果。這里的另一個(gè) JVM 可以在同一臺(tái)計(jì)算機(jī)也可以是遠(yuǎn)程計(jì)算機(jī)。因此,RMI 意味著需要一個(gè) Server 端和一個(gè) Client 端。

Server 端通常會(huì)創(chuàng)建一個(gè)對(duì)象,并使之可以被遠(yuǎn)程訪(fǎng)問(wèn)。

  • 這個(gè)對(duì)象被稱(chēng)為遠(yuǎn)程對(duì)象。
  • Server 端需要注冊(cè)這個(gè)對(duì)象可以被 Client 遠(yuǎn)程訪(fǎng)問(wèn)。

Client 端調(diào)用可以被遠(yuǎn)程訪(fǎng)問(wèn)的對(duì)象上的方法,Client 端就可以和 Server 端進(jìn)行通信并相互傳遞信息。

說(shuō)到這里,是不是發(fā)現(xiàn)使用 RMI 在構(gòu)建一個(gè)分布式應(yīng)用時(shí)十分方便,它和 RPC 一樣可以實(shí)現(xiàn)分布式應(yīng)用之間的互相通信,甚至和現(xiàn)在的微服務(wù)思想都十分類(lèi)似。

RMI 工作原理

正所謂 “知其然知其所以然”,在開(kāi)始編寫(xiě) RMI 代碼之前,有必要了解一下 RMI 的工作原理,RMI 中 Client 端是和 Server 端是如何通信的呢?

下圖的可以幫助我們理解RMI 的工作流程。

RMI Connection

從圖中可以看到,Client 端有一個(gè)被稱(chēng) Stub 的東西,有時(shí)也會(huì)被成為存根,它是 RMI Client  的代理對(duì)象,Stub 的主要功能是請(qǐng)求遠(yuǎn)程方法時(shí)構(gòu)造一個(gè)信息塊,RMI 協(xié)議會(huì)把這個(gè)信息塊發(fā)送給 Server 端。

這個(gè)信息塊由幾個(gè)部分組成:

  • 遠(yuǎn)程對(duì)象標(biāo)識(shí)符。
  • 調(diào)用的方法描述。
  • 編組后的參數(shù)值(RMI協(xié)議中使用的是對(duì)象序列化)。

既然 Client 端有一個(gè) Stub 可以構(gòu)造信息快發(fā)送給 Server 端,那么 Server 端必定會(huì)有一個(gè)接收這個(gè)信息快的對(duì)象,稱(chēng)為 Skeleton 。

它主要的工作是:

解析信息塊中的調(diào)用對(duì)象標(biāo)識(shí)符和方法描述,在 Server 端調(diào)用具體的對(duì)象方法。

取得調(diào)用的返回值或者異常值。

把返回值進(jìn)行編組,返回給客戶(hù)端 Stub.

到這里,一次從  Client 端對(duì) Server 端的調(diào)用結(jié)果就可以獲取到了。

RMI 開(kāi)發(fā)

通過(guò)上面的介紹,知道了 RMI 的概念以及 RMI 的工作原理,下面介紹 RMI 的開(kāi)發(fā)流程。

這里會(huì)通過(guò)一個(gè)場(chǎng)景進(jìn)行演示,假設(shè) Client 端需要查詢(xún)用戶(hù)信息,而用戶(hù)信息存在于 Server 端,所以在 Server 端開(kāi)放了 RMI 協(xié)議接口供客戶(hù)端調(diào)用查詢(xún)。

RMI Server

Server 端主要是構(gòu)建一個(gè)可以被傳輸?shù)念?lèi) User,一個(gè)可以被遠(yuǎn)程訪(fǎng)問(wèn)的類(lèi) UserService,同時(shí)這個(gè)對(duì)象要注冊(cè)到 RMI 開(kāi)放給客戶(hù)端使用。

定義服務(wù)器接口(需要繼承 Remote 類(lèi),方法需要拋出 RemoteException)。

  1. package com.wdbyte.rmi.server; 
  2.  
  3. import java.rmi.Remote; 
  4. import java.rmi.RemoteException; 
  5.  
  6.  
  7. /** 
  8.  * RMI Server 
  9.  * 
  10.  * @author www.wdbyte.com 
  11.  * @date 2021/05/08 
  12.  */ 
  13. public interface UserService extends Remote { 
  14.  
  15.     /** 
  16.      * 查找用戶(hù) 
  17.      *  
  18.      * @param userId 
  19.      * @return 
  20.      * @throws RemoteException 
  21.      */ 
  22.     User findUser(String userId) throws RemoteException; 

User 對(duì)象在步驟 3 中定義。

實(shí)現(xiàn)服務(wù)器接口(需要繼承 UnicastRemoteObject 類(lèi),實(shí)現(xiàn)定義的接口)。

  1. package com.wdbyte.rmi.server; 
  2.  
  3. import java.rmi.RemoteException; 
  4. import java.rmi.server.UnicastRemoteObject; 
  5.  
  6. /** 
  7.  * @author www.wdbyte.com 
  8.  * @date 2021/05/08 
  9.  */ 
  10. public class UserServiceImpl extends UnicastRemoteObject implements UserService { 
  11.  
  12.     protected UserServiceImpl() throws RemoteException { 
  13.     } 
  14.  
  15.     @Override 
  16.     public User findUser(String userId) throws RemoteException { 
  17.         // 加載在查詢(xún) 
  18.          if ("00001".equals(userId)) { 
  19.             User user = new User(); 
  20.             user.setName("金庸"); 
  21.             user.setAge(100); 
  22.             user.setSkill("寫(xiě)作"); 
  23.             return user
  24.         } 
  25.         throw new RemoteException("查無(wú)此人"); 
  26.     } 

定義傳輸?shù)膶?duì)象,傳輸?shù)膶?duì)象需要實(shí)現(xiàn)序列化(Serializable)接口。

需要傳輸?shù)念?lèi)一定要實(shí)現(xiàn)序列化接口,不然傳輸時(shí)會(huì)報(bào)錯(cuò)。IDEA 中如何生成 serialVersionUID,在文章末尾也附上了簡(jiǎn)單教程。

  1. package com.wdbyte.rmi.server; 
  2.  
  3. import java.io.Serializable
  4.  
  5. /** 
  6.  * 
  7.  * @author www.wdbyte.com 
  8.  * @date 2021/05/08 
  9.  */ 
  10. public class User implements Serializable { 
  11.  
  12.     private static final long serialVersionUID = 6490921832856589236L; 
  13.  
  14.     private String name
  15.     private Integer age; 
  16.     private String skill; 
  17.  
  18.     public String getName() { 
  19.         return name
  20.     } 
  21.  
  22.     public void setName(String name) { 
  23.         this.name = name
  24.     } 
  25.  
  26.     public Integer getAge() { 
  27.         return age; 
  28.     } 
  29.  
  30.     public void setAge(Integer age) { 
  31.         this.age = age; 
  32.     } 
  33.  
  34.     public String getSkill() { 
  35.         return skill; 
  36.     } 
  37.  
  38.     public void setSkill(String skill) { 
  39.         this.skill = skill; 
  40.     } 
  41.      
  42.     @Override 
  43.     public String toString() { 
  44.         return "User{" + 
  45.             "name='" + name + '\'' + 
  46.             ", age=" + age + 
  47.             ", skill='" + skill + '\'' + 
  48.             '}'
  49.     } 

注冊(cè)( rmiregistry)遠(yuǎn)程對(duì)象,并啟動(dòng)服務(wù)端程序。

服務(wù)端綁定了 UserService 對(duì)象作為遠(yuǎn)程訪(fǎng)問(wèn)的對(duì)象,啟動(dòng)時(shí)端口設(shè)置為 1900。

  1. package com.wdbyte.rmi.server; 
  2.  
  3. import java.rmi.Naming; 
  4. import java.rmi.registry.LocateRegistry; 
  5.  
  6. /** 
  7.  * RMI Server 端 
  8.  * 
  9.  * @author https://www.wdbyte.com 
  10.  * @date 2021/05/08 
  11.  */ 
  12. public class RmiServer { 
  13.  
  14.     public static void main(String[] args) { 
  15.         try { 
  16.             UserService userService = new UserServiceImpl(); 
  17.             LocateRegistry.createRegistry(1900); 
  18.             Naming.rebind("rmi://localhost:1900/user", userService); 
  19.             System.out.println("start server,port is 1900"); 
  20.         } catch (Exception e) { 
  21.             e.printStackTrace(); 
  22.         } 
  23.     } 

RMI Client

相比 Server 端,Client 端就簡(jiǎn)單的多。直接引入可遠(yuǎn)程訪(fǎng)問(wèn)和需要傳輸?shù)念?lèi),通過(guò)端口和 Server 端綁定的地址,就可以發(fā)起一次調(diào)用。

  1. package com.wdbyte.rmi.client; 
  2.  
  3. import java.rmi.Naming; 
  4.  
  5. import com.wdbyte.rmi.server.User
  6. import com.wdbyte.rmi.server.UserService; 
  7.  
  8. /** 
  9.  * @author https://www.wdbyte.com 
  10.  * @date 2021/05/08 
  11.  */ 
  12. public class RmiClient { 
  13.     public static void main(String args[]) { 
  14.         User answer; 
  15.         String userId = "00001"
  16.         try { 
  17.             // lookup method to find reference of remote object 
  18.             UserService access = (UserService)Naming.lookup("rmi://localhost:1900/user"); 
  19.             answer = access.findUser(userId); 
  20.             System.out.println("query:" + userId); 
  21.             System.out.println("result:" + answer); 
  22.         } catch (Exception ae) { 
  23.             System.out.println(ae); 
  24.         } 
  25.     } 

RMI  測(cè)試

啟動(dòng) Server 端。

  1. start server,port is 1900 

啟動(dòng) Client 端。

  1. query:00001 
  2. result:User{name='金庸', age=100, skill='寫(xiě)作'

如果 Client 端傳入不存在的 userId。

  1. java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:  
  2.     java.rmi.RemoteException: 查無(wú)此人 

serialVersionUID 的生成

IDEA 中生成 serialVersionUID,打開(kāi)設(shè)置,如下圖所示勾選。

IDEA 設(shè)置

選中要生成 serialVersionUID 的類(lèi),按智能提示快捷鍵。

IDEA serialVersionUID

參考

[1] https://docs.oracle.com/javase/tutorial/rmi/overview.html

 

責(zé)任編輯:武曉燕 來(lái)源: 未讀代碼
相關(guān)推薦

2012-04-11 11:10:25

JavaRMI

2011-03-28 10:42:00

Spring

2012-02-07 13:21:37

Java

2018-02-28 14:04:08

RMIJDBC存儲(chǔ)

2009-06-19 14:23:41

RMIJava分布式計(jì)算

2010-08-25 17:08:18

實(shí)例教程

2013-05-29 09:59:20

Java-RMI遠(yuǎn)程調(diào)用

2009-06-08 21:49:25

RowSetJava

2016-09-18 16:58:09

JavaProperties

2012-03-27 14:04:54

JavaEnum

2019-06-21 14:48:25

RMI遠(yuǎn)程RPC

2012-06-02 00:53:39

Javafinally

2017-09-23 15:28:32

JavaOptional方法

2024-01-31 08:53:01

Java數(shù)組代碼

2021-04-13 09:20:21

JavaUnsafejava8

2018-06-12 15:10:49

RPCRM企業(yè)

2010-03-11 15:39:01

Python編程語(yǔ)言

2024-01-30 09:43:43

Java緩存技術(shù)

2016-11-03 18:39:39

JavaMySQL

2024-01-11 13:21:53

開(kāi)發(fā)代碼
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)