天天看點

RMI 使用筆記

Java 遠端方法調用,即 Java RMI( Java Remote Method Invocation ) 。顧名思義,可以使客戶機上運作的程式能夠調用遠端伺服器上的對象(方法)。

下面主要介紹一下使用步驟:

1.定義遠端接口(服務端)

遠端接口定義出可以讓客戶遠端調用的方法。

此接口必須實作 

java.rmi.Remote

 接口,來表示其支援遠端調用;同時其中聲明的所有方法,需要抛出

RemoteException

異常,因為遠端調用的不穩定性(如網絡原因等),這樣可以讓用戶端在調用失敗時進行相應的處理。

public interface DemoService extends Remote {
    String sayHello() throws RemoteException;
}      

2.實作遠端接口(服務端)

遠端接口的實作類如果想要被遠端通路,可以有如下實作方式:

繼承

java.rmi.server.UnicastRemoteObject

RMI 使用筆記
public class DemoServerImpl extends UnicastRemoteObject implements DemoService{
​
    public DemoServerImpl() throws RemoteException {
        // 因為 UnicastRemoteObject 構造器抛出 RemoteException
        // 是以此處隻能聲明一個構造器并抛出對應異常
    }
​
    @Override
    public String sayHello() throws RemoteException {
        return "Hello World";
    }
}      
RMI 使用筆記

如果不想繼承

UnicastRemoteObject

類,則需要使用 

UnicastRemoteObject

類的靜态方法

exportObject(Remote obj, int port)

将對象導出

其中如果端口設為 0 的話,則表示任何合适的端口都可用來監聽客戶連接配接

RMI 使用筆記
public class DemoServerImpl implements DemoService{
​
    public DemoServerImpl() throws RemoteException {
        UnicastRemoteObject.exportObject(this, 0);
    }
​
    @Override
    public String sayHello() throws RemoteException {
        return "Hello World";
    }
}      
RMI 使用筆記

這兩者方法本質上是一樣的,在

UnicaseRemoteObject

類的構造方法中,其實也是調用了

exportObject

方法

RMI 使用筆記
// UnicaseRemoteObject中的部分源碼
protected UnicastRemoteObject() throws RemoteException
{
    this(0);
}
// if port is zero, an anonymous port is chosen
protected UnicastRemoteObject(int port) throws RemoteException
{
    this.port = port;
    exportObject((Remote) this, port);
}      
RMI 使用筆記

3.啟動 RMI 系統資料庫

系統資料庫就像一個電話簿,啟動後即可将提供的服務注冊到其中,客戶可以通過它查詢到服務來進行調用

啟動系統資料庫有兩種方法,一種是通過指令行

rmiregistry

來啟動,另一種方式是通過

LocateRegistry.createRegistry(int port)

方法。

4.注冊開啟遠端服務

注冊服務共有三種方式:

  1. LocateRegistry 類的對象的 rebind() 和 lookup() 來實作綁定注冊和查找遠端對象的
  2. 利用命名服務 java.rmi.Naming 類的 rebind() 和 lookup() 來實作綁定注冊和查找遠端對象的
  3. 利用JNDI(Java Naming and Directory Interface,Java命名和目錄接口) java.naming.InitialContext 類來 rebind() 和 lookup() 來實作綁定注冊和查找遠端對象的

其中第二種方式實際是對第一種方式的簡單封裝,在内部仍是調用

Registry

類的

bind

方法

RMI 使用筆記
// Naming 類的部分源碼 (為了節省篇幅,去除了抛出異常部分)
public static void bind(String name, Remote obj) throws ...
{
    ParsedNamingURL parsed = parseURL(name);
    Registry registry = getRegistry(parsed);
​
    if (obj == null)
        throw new NullPointerException("cannot bind to null");
​
    registry.bind(parsed.name, obj);
}      
RMI 使用筆記

服務測試類:

RMI 使用筆記
public class ServerTest {
    public static void main(String[] args) throws Exception{
        String name = "rmi.service.DemoService";
        // 建立服務
        DemoService service = new DemoServerImpl();
        // 建立本機 1099 端口上的 RMI 系統資料庫
        Registry registry1 = LocateRegistry.createRegistry(1099);
      
        /***************** 以下為注冊方法一 ************/
        // 将服務綁定到系統資料庫中
        registry1.bind(name, service);
      
        /***************** 以下為注冊方法二 ************/
        // Naming.bind(name, service);
      
        /***************** 以下為注冊方法三 ************/
        //Context namingContext = new InitialContext();
        //namingContext.bind("rmi:" + name, service); // 此方式 name 需要以 rmi: 開頭
      
    }
}      
RMI 使用筆記

用戶端測試類:

RMI 使用筆記
public class ClientTest {
    public static void main(String[] args) throws Exception {
        String name = "rmi.service.DemoService";
        /***************** 以下為查找服務方法一 ************/
        // 擷取系統資料庫
        Registry registry = LocateRegistry.getRegistry("localhost", 1099);
        // 查找對應的服務
        DemoService service = (DemoService) registry.lookup(name);
      
        /***************** 以下為查找服務方法二 ************/
        // DemoService service = (DemoService) Naming.lookup(name);
      
        /***************** 以下為查找服務方法三 ************/
        //Context namingContext = new InitialContext();
        //DemoService service = (DemoService) namingContext.lookup("rmi:" + name);
      
        // 調用服務
        System.out.println(service.sayHello());
    }
}      

轉載:https://www.cnblogs.com/zawier/p/7043855.html