溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java的RMI如何使用

發(fā)布時間:2022-02-28 10:41:57 來源:億速云 閱讀:130 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹“Java的RMI如何使用”,在日常操作中,相信很多人在Java的RMI如何使用問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Java的RMI如何使用”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

RMI 介紹

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

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

這個對象被稱為遠(yuǎn)程對象。Server 端需要注冊這個對象可以被 Client 遠(yuǎn)程訪問。

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

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

RMI 工作原理

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

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

Java的RMI如何使用

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

這個信息塊由幾個部分組成:

  • 遠(yuǎn)程對象標(biāo)識符。

  • 調(diào)用的方法描述。

  • 編組后的參數(shù)值(RMI協(xié)議中使用的是對象序列化)。

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

它主要的工作是:

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

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

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

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

RMI 開發(fā)

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

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

RMI Server

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

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

package com.wdbyte.rmi.server;

import java.rmi.Remote;
import java.rmi.RemoteException;


/**
 * RMI Server
 *
 * @author www.wdbyte.com
 * @date 2021/05/08
 */
public interface UserService extends Remote {

    /**
     * 查找用戶
     * 
     * @param userId
     * @return
     * @throws RemoteException
     */
    User findUser(String userId) throws RemoteException;
}

User 對象在步驟 3 中定義。

2.實現(xiàn)服務(wù)器接口(需要繼承 UnicastRemoteObject 類,實現(xiàn)定義的接口)。

package com.wdbyte.rmi.server;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

/**
 * @author www.wdbyte.com
 * @date 2021/05/08
 */
public class UserServiceImpl extends UnicastRemoteObject implements UserService {

    protected UserServiceImpl() throws RemoteException {
    }

    @Override
    public User findUser(String userId) throws RemoteException {
        // 加載在查詢
         if ("00001".equals(userId)) {
            User user = new User();
            user.setName("金庸");
            user.setAge(100);
            user.setSkill("寫作");
            return user;
        }
        throw new RemoteException("查無此人");
    }
}

3.定義傳輸?shù)膶ο?,傳輸?shù)膶ο笮枰獙崿F(xiàn)序列化(Serializable)接口。

需要傳輸?shù)念愐欢ㄒ獙崿F(xiàn)序列化接口,不然傳輸時會報錯。IDEA 中如何生成 serialVersionUID,在文章末尾也附上了簡單教程。

package com.wdbyte.rmi.server;

import java.io.Serializable;

/**
 *
 * @author www.wdbyte.com
 * @date 2021/05/08
 */
public class User implements Serializable {

    private static final long serialVersionUID = 6490921832856589236L;

    private String name;
    private Integer age;
    private String skill;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getSkill() {
        return skill;
    }

    public void setSkill(String skill) {
        this.skill = skill;
    }
    
    @Override
    public String toString() {
        return "User{" +
            "name='" + name + ''' +
            ", age=" + age +
            ", skill='" + skill + ''' +
            '}';
    }
}

4.注冊( rmiregistry)遠(yuǎn)程對象,并啟動服務(wù)端程序。

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

package com.wdbyte.rmi.server;

import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;

/**
 * RMI Server 端
 *
 * @author https://www.wdbyte.com
 * @date 2021/05/08
 */
public class RmiServer {

    public static void main(String[] args) {
        try {
            UserService userService = new UserServiceImpl();
            LocateRegistry.createRegistry(1900);
            Naming.rebind("rmi://localhost:1900/user", userService);
            System.out.println("start server,port is 1900");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

RMI Client

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

package com.wdbyte.rmi.client;

import java.rmi.Naming;

import com.wdbyte.rmi.server.User;
import com.wdbyte.rmi.server.UserService;

/**
 * @author https://www.wdbyte.com
 * @date 2021/05/08
 */
public class RmiClient {
    public static void main(String args[]) {
        User answer;
        String userId = "00001";
        try {
            // lookup method to find reference of remote object
            UserService access = (UserService)Naming.lookup("rmi://localhost:1900/user");
            answer = access.findUser(userId);
            System.out.println("query:" + userId);
            System.out.println("result:" + answer);
        } catch (Exception ae) {
            System.out.println(ae);
        }
    }
}

RMI 測試

啟動 Server 端。

start server,port is 1900

啟動 Client 端。

query:00001
result:User{name='金庸', age=100, skill='寫作'}

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

java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
	java.rmi.RemoteException: 查無此人

serialVersionUID 的生成

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

選中要生成 serialVersionUID 的類,按智能提示快捷鍵。

    到此,關(guān)于“Java的RMI如何使用”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI