首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

RMI 分散式應用開發全流程實戰:從介面定義到部署執行

     編輯:Java 相關知識

RMI (Remote Method Invocation) 是 Java 原生分散式物件機制,也是 EJB 底層支柱。本文以「遠端計算機服務」為例,完整演示 RMI 系統開發的七大步驟:介面定義、實作、Stub 生成、Server/Client 開發、Registry 啟動、安全策略、分散式執行驗證。

RMI 系統六大核心組件

  1. 遠端介面 (extends Remote)
  2. 遠端實作 (extends UnicastRemoteObject)
  3. Stub (Client 代理) / Skeleton (Server 骨架)
  4. Server 主程式 (啟動、註冊)
  5. RMI Registry (命名服務,預設埠 1099)
  6. Client 程式 (查找、呼叫)
  7. 類別檔案提供者 (HTTP/FTP/Codebase)

完整開發實戰

步驟 1:定義遠端介面 Calculator.java


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

public interface Calculator extends Remote {
    long add(long a, long b) throws RemoteException;
    long sub(long a, long b) throws RemoteException;
    long mul(long a, long b) throws RemoteException;
    long div(long a, long b) throws RemoteException;
}

鐵律:介面 `public`、繼承 `Remote`、所有方法 `throws RemoteException`。

步驟 2:實作遠端介面 CalculatorImpl.java


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

public class CalculatorImpl extends UnicastRemoteObject implements Calculator {
    // 必須顯式建構子並拋出 RemoteException
    public CalculatorImpl() throws RemoteException {
        super(); // 啟動 RMI 連結、匯出物件
    }

    public long add(long a, long b) throws RemoteException { return a + b; }
    public long sub(long a, long b) throws RemoteException { return a - b; }
    public long mul(long a, long b) throws RemoteException { return a * b; }
    public long div(long a, long b) throws RemoteException { return a / b; }
}

關鍵點:繼承 `UnicastRemoteObject` 表示單點 TCP 連線遠端物件。若不繼承,需手動呼叫 `UnicastRemoteObject.exportObject(this)`。

步驟 3:生成 Stub/Skeleton


javac Calculator.java CalculatorImpl.java
rmic CalculatorImpl

產生:`CalculatorImpl_Stub.class` (Client 代理)、`CalculatorImpl_Skel.class` (Server 骨架,JDK 1.2+ 可選)。

步驟 4:開發 Server CalculatorServer.java


import java.rmi.Naming;
import java.rmi.RemoteException;

public class CalculatorServer {
    public CalculatorServer() {
        try {
            Calculator calc = new CalculatorImpl();
            // 註冊到 Registry:rmi://host:port/name
            Naming.rebind("rmi://localhost:1099/CalculatorService", calc);
            System.out.println("CalculatorService bound in registry");
        } catch (Exception e) {
            System.out.println("Trouble: " + e);
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new CalculatorServer();
    }
}

步驟 5:開發 Client CalculatorClient.java


import java.rmi.Naming;
import java.rmi.RemoteException;
import java.net.MalformedURLException;
import java.rmi.NotBoundException;

public class CalculatorClient {
    public static void main(String[] args) {
        try {
            // 從 Registry 查找遠端物件參考
            Calculator calc = (Calculator) Naming.lookup("rmi://localhost/CalculatorService");
            
            // 想像呼叫本地方法,實則跨 JVM 執行
            System.out.println("4 - 3 = " + calc.sub(4, 3));
            System.out.println("4 + 5 = " + calc.add(4, 5));
            System.out.println("3 * 6 = " + calc.mul(3, 6));
            System.out.println("9 / 3 = " + calc.div(9, 3));
        } catch (MalformedURLException | RemoteException | NotBoundException e) {
            e.printStackTrace();
        } catch (ArithmeticException e) {
            System.out.println("ArithmeticException: " + e.getMessage());
        }
    }
}

分散式部署與執行 (三終端機驗證)

終端機 1:啟動 RMI Registry


# 確保在類別檔案目錄下執行
rmiregistry
# 或指定埠
rmiregistry 4500

終端機 2:啟動 Server (需安全策略)

建立 `policy.txt`:


grant {
    permission java.security.AllPermission "", "";
};

生產環境嚴禁使用 AllPermission,此處僅示範。


java -Djava.security.policy=policy.txt CalculatorServer

終端機 3:啟動 Client


java CalculatorClient

預期輸出


4 - 3 = 1
4 + 5 = 9
3 * 6 = 18
9 / 3 = 3

跨機器部署關鍵調整

組件本機部署跨機器部署
Registrylocalhost:1099Server IP:1099 (Server 機器啟動)
Server 註冊rmi://localhost:1099/namermi://server-ip:1099/name
Client 查找rmi://localhost/namermi://server-ip/name
Client 需檔案所有 class介面 + Stub 類別
Server 需檔案所有 class實作 + Stub/Skeleton + 介面

進階優化:動態類別載入 (Codebase)

避免手動複製 Stub/介面類別:

  1. Server 機器啟動 HTTP 伺服器 (如 `python -m http.server 8000`) 托管類別目錄
  2. Server 啟動參數:-Djava.rmi.server.codebase=https://server-ip:8000/
  3. Client 自動從 codebase 下載缺少的類別

常見問題排查

  • ClassNotFoundException (Stub):`rmic` 未執行或 Classpath 缺少 Stub 類別
  • ConnectException:Registry 未啟動、埠號錯誤、防火牆阻擋
  • SecurityException:缺少安全策略檔或權限不足
  • UnmarshalException:Client/Server 類別版本不一致 (serialVersionUID)
  • Stub 不同步:修改介面/實作後必須重新 `rmic` 並重新部署

RMI 核心架構優勢總結

  • 語言原生:無需 IDL、無額外編譯步驟 (除 rmic)
  • 物件語義:遠端呼叫如同本地呼叫,支援物件傳遞 (序列化)
  • 分散式 GC:自動管理遠端物件生命週期
  • 安全整合:Java 安全架構無縫整合
  • 動態載入:Codebase 機制簡化部署

總結

RMI 以「介面驅動、Stub 代理、Registry 命名」三大支柱構建 Java 分散式系統。本文計算機服務範例完整覆蓋開發、編譯、Stub 生成、註冊、查找、呼叫、安全策略、跨機器部署全生命週期。掌握此流程,即掌握 Java 分散式程式設計的核心內功,也是理解 EJB、Jini、分散式 Spring Remoting 的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved