天天看點

淺談RMI - 搭建一個簡單的RMI程式聲明:本案例使用的IDE是Eclipse,用戶端程式和伺服器程式位于同一個project中。 一、基本原理二、基本步驟*建立遠端接口三、建立遠端類四、建立伺服器程式五、建立用戶端程式六、運作

聲明:本案例使用的IDE是Eclipse,用戶端程式和伺服器程式位于同一個project中。

一、基本原理

RMI是Remote Method Invoke的縮寫,是JDK提供的一個完善的、簡單易用的遠端調用架構,它要求用戶端和伺服器端都是Java程式。下面簡述RMI的基本原理:如下圖所示,RMI采用代理來負責用戶端和伺服器之間socket通信的細節。RMI架構分别為遠端對象生成了用戶端代理和伺服器端代理,位于用戶端的代理稱為存根(Stub),位于伺服器端的代理稱為骨架(Skeleton)。

淺談RMI - 搭建一個簡單的RMI程式聲明:本案例使用的IDE是Eclipse,用戶端程式和伺服器程式位于同一個project中。 一、基本原理二、基本步驟*建立遠端接口三、建立遠端類四、建立伺服器程式五、建立用戶端程式六、運作

遠端對象會在用戶端生成存根對象。當用戶端調用遠端對象的方法時,實際上是調用本地存根的相應方法。然後,存根會把被通路的遠端對象名、方法名以及參數編組後發送給伺服器,由骨架去調用相應的遠端方法并把傳回值或異常傳回給用戶端。

二、基本步驟

一般來說,隻要繼承java.rmi.server.UnicastRemoteObject類和實作java.rmi.Remote 接口就可以成為遠端對象。由于java的單繼承,繼承了UnicastRemoteObject類之後就不能繼承其他的類,這時可以在構造方法中調用exportObect()方法,同樣可以将其導為遠端對象。實際上,UnicastRemoteObject的構造器也會去調用自身的exportObect()的靜态方法。 下面是建立一個RMI程式的基本步驟: (1)建立遠端接口,繼承java.rmi.Remote接口; (2)建立遠端類,實作遠端接口; (3)建立伺服器程式,在rmiregistry系統資料庫中注冊遠端對象; (4)建立用戶端程式,負責定位遠端對象,并且調用遠端方法。

*建立遠端接口

遠端接口中聲明了可以被用戶端通路的遠端方法,遠端接口應符合以下條件: (1)直接或間接繼承java.rmi.Remote接口; (2)接口中的所有方法聲明抛出java.rmi.RemoteException異常或父異常。

package main;

import java.rmi.Remote;
import java.rmi.RemoteException;
// Inherit the java.rmi.Remote interface
public interface HelloService extends Remote {
    // Remote method should throw RemoteException
    public String service(String data) throws RemoteException;
}
           

三、建立遠端類

遠端類應符合以下條件: (1)繼承java.rmi.server.UnicastRemoteObject類并實作遠端接口; (2)構造器必須抛出java.rmi.RemoteException異常。

package main;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
// Inherit UnicastRemoteObject and implement HelloService interface
public class HelloServiceImpl extends UnicastRemoteObject
        implements HelloService {

    private static final long serialVersionUID = 1L;
    private String name;

    public HelloServiceImpl(String name) throws RemoteException {
        super();
        this.name = name;
        // UnicastRemoteObject.exportObject(this, 0);
    }

    @Override
    public String service(String data) throws RemoteException {
        return data + name;
    }
}
           

四、建立伺服器程式

在這裡要介紹幾個方法:

  • bind(String name, Object obj): 注冊對象,把對象與服務名綁定。如果該服務名已與其他對象綁定,則會抛出NameAlreadyBoundException異常。
  • rebind(String name, Object obj): 注冊對象,把對象與服務名綁定。如果該服務名已與其他對象綁定,不會抛異常,而是将新的對象綁定到該服務名上。
  • lookup(String name): 查找對象,傳回與指定名稱相同的對象。

伺服器端首先要建立系統資料庫執行個體,然後将遠端對象注冊到系統資料庫上。伺服器程式運作就緒之後,不會立即結束,而是去監控用戶端的連接配接。關于服務名的命名格式,推薦使用“rmi://主機名:端口号/執行個體名”的方式,這樣可以避免在遠端對象很多的時候因服務名一緻而引發的沖突。預設的端口号1099可以省略。

package main;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class Server {

    public static void main(String[] args) {
        try {
            LocateRegistry.createRegistry(1099);

            HelloService service1 = new HelloServiceImpl("service1");
            Context namingContext = new InitialContext();
            namingContext.rebind("rmi://localhost:1099/HelloService1",
                    service1);
        }
        catch (RemoteException | NamingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("Successfully register a remote object.");

    }
}
           

五、建立用戶端程式

package main;

import java.rmi.RemoteException;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class Client {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        String url = "rmi://localhost:1099/";
        try {
            Context namingContext = new InitialContext();
            HelloService serv = (HelloService) namingContext.lookup(
                    url + "HelloService1");
            String data = "This is RMI Client.";
            System.out.println(serv.service(data));
        }
        catch (NamingException | RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
           

用戶端先根據服務名查找遠端對象,然後才能調用遠端方法。是以,此處的服務名必須與在伺服器中注冊的服務名稱一緻,否則将無法找到遠端對象。

六、運作

在Eclipse中先啟動Server,然後啟動Client即可。