2010年11月14日 星期日

[Java] RMI

名詞解釋:在RMI中,用戶端的helper稱為stub,而伺服器端的helper稱為skeleton, 示意圖
        (RMI STUB)   (RMI SKELETON)  
client    client<------>service     service
object    helper        helper      object

建構遠端服務(serice)
步驟一:建構Remote interface
* extend過java.rmi.Remote
* 宣告所有的method都會拋出RemoteException
* 確定參數與回傳值都是primitive或Serializable
import java.rmi.*;

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

步驟二:實做Remote
* 實做Remote這個interface
* extend過UnicastRemoteObject
* 撰寫宣告RemoteException的無參數constructor
* 向RMI registry登記服務
import java.rmi.*;
import java.rmi.server.*;

public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote {
    public String sayHello() {
        return "Server says, 'Hey'";
    }   

    public MyRemoteImpl() throws RemoteException {}

    public static void main(String[] args) {
        try {
            MyRemote service = new MyRemoteImpl();
            Naming.rebind("//127.0.0.1/Remote", service);
        } catch (Exception ex) {
            ex.printStackTrace();
        }   
    }   
}

步驟三:以rmic產生stub與skeleton
* 對實做出的class(非interface)執行rmic
$ rmic MyRemoteImpl

步驟四:啟動RMI registry(rmiregistry)
* 叫出命令列來啟動rmiregistry
$ rmiregistry

步驟五:啟動遠端服務
* 叫出另一個命令列來啟動服務
$ java MyRemoteImpl


建構用戶端(client)
* 用戶端查詢RMI registry
* RMI registry傳回stub物件
* 用戶端就像取用真正的服務一樣的叫用stub上的method
import java.rmi.*;

public class MyRemoteClient {
    public static void main(String[] args) {
        new MyRemoteClient().go();
    }   

    public void go() {
        try {
            MyRemote service = (MyRemote) Naming.lookup("rmi://127.0.0.1/Remote");
            String s = service.sayHello();

            System.out.println(s);

        } catch (Exception ex) {
            ex.printStackTrace();
        }   
    }   
}

注意事項:
* RMI在網路間的傳遞過程一樣使用socket
* 啟動遠端服務之前需先啟動rmiregistry
* client端需要有service端的stub和interface(*.class)

範例來自深入淺出Java程式設計

沒有留言: