1. 程式人生 > >java RMI介紹及入門

java RMI介紹及入門

遠端方法呼叫

1.概述

分散式計算的關鍵是遠端方法呼叫,在一臺計算機上的某些程式碼希望呼叫另一臺計算機上的某個物件的方法。本文介紹的RMI協議就可以解決這種問題。

2.工作原理

在這裡插入圖片描述
基本結構如上:
1.當客戶端要呼叫遠端方法時,實際上呼叫的是儲存在客戶端的一個普通物件,叫存根(stub)
存根將遠端方法所需引數打包成一組位元組。對引數編碼的過程稱為引數編組,目的是轉換成適合在虛擬機器之間進行傳遞的格式。最後存根將此資訊傳送給伺服器。
2.服務端收到客戶端發來的訊息,定位要呼叫的遠端物件,呼叫所需方法,傳遞引數;捕獲返回值或者呼叫產生的異常;將返回值編組,打包送給客戶端存根。

3.示例Demo

/**
 * @Auther: 18030501
 * @Date: 2018/11/1 20:27
 * @Description:
 */
public interface IHello extends Remote, Serializable {

    public String sayHelloToSomeBody(String name) throws RemoteException;
}

/**
 * @Auther: 18030501
 * @Date: 2018/11/1 20:28
 * @Description: 繼承UnicastRemoteObject表示HelloImpl是一個單獨的、不能複製的、遠端的物件
 */
public class HelloImpl extends UnicastRemoteObject implements IHello {

    // 構造方法需要丟擲RemoteException異常
    public HelloImpl() throws RemoteException {
    }

    @Override
    public String sayHelloToSomeBody(String name) throws RemoteException {
        System.out.println("你好:" + name);
        return "OK";
    }
}

/**
 * @Auther: 18030501
 * @Date: 2018/11/1 20:30
 * @Description:
 */
public class HelloServer {

    /**
     * 註冊服務共有三種方式:
     * LocateRegistry 類的物件的 rebind() 和 lookup() 來實現繫結註冊和查詢遠端物件的
     * 利用命名服務 java.rmi.Naming 類的 rebind() 和 lookup() 來實現繫結註冊和查詢遠端物件的
     * 利用JNDI(Java Naming and Directory Interface,Java命名和目錄介面) java.naming.InitialContext 類來 rebind() 和 lookup() 來實現繫結註冊和查詢遠端物件的
     */
    public static void main(String[] args) {
        try {
            // 建立一個遠端物件
            IHello hello = new HelloImpl();
            // 使用自舉註冊服務註冊物件到登錄檔中
            LocateRegistry.createRegistry(8888);
            // rmi://host:port/遠端物件名,遠端物件名是要與此物件繫結的
            Naming.bind("rmi://10.49.2.18:8888/RHello", hello);
            System.out.println("等待客戶端呼叫...");
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (AlreadyBoundException e) {
            System.out.println("已經繫結");
            e.printStackTrace();
        } catch (MalformedURLException e) {
            System.out.println("無效url");
            e.printStackTrace();
        }
    }
}

/**
 * @Auther: 18030501
 * @Date: 2018/11/1 20:30
 * @Description:
 */
public class HelloClient {

    public static void main(String[] args) throws Exception {

        // 指定伺服器與遠端物件名字
        String url = "rmi://10.49.2.18:8888/RHello";
        String[] list = Naming.list(url);
        for (String s : list) {
            System.out.println(s);
        }
        IHello hello = (IHello) Naming.lookup(url);
        hello.sayHelloToSomeBody("拿著核武器的程式設計師");
    }
}