2009-07-27 40 views
8

我有一個客戶端,在服務器上啓動一個長時間運行的進程。定期,我想向用戶展示背景中發生的事情。最簡單的方法是輪詢服務器,但我想知道是否沒有辦法爲此實現Observer模式。不幸的是,我正在使用RMI與服務器交談,我擔心我必須將我的客戶端變成RMI服務器。如何使用Java RMI實現觀察者模式?

是否有另一種我失蹤的方式?

+1

我試圖做到這一點,以及和我來到了相同的結論...... RMI有點太差勁了! :) – JohnIdol 2009-12-15 19:06:56

回答

1

我不認爲你錯過了任何東西。唯一的兩種方法是定期調用服務器並檢查狀態(輪詢)或註冊服務器定期調用的回調(您的客戶端必須公開方法)。國際海事組織,輪詢是一個完全合理的方式來處理這一點。

3

RMI一般可以支持雙向通信。 (是的,RMI是一個PITA來設置,並做任何事情。)

但是,通過CGI腳本(!)工作的HTTP傳輸不支持它。

+0

當我使用LocateRegistry.createRegistry()在代碼中啓動服務器(而不是使用Sun提供的可執行文件)時,仍然如此嗎? – 2009-07-28 08:11:13

+0

+1「(是的,RMI是PITA的設置,並與其他做任何事情。)」請告訴我的學校說。 – Luc 2014-06-13 23:00:56

2

這裏整合所有的答案,我實現了2路RMI客戶端和服務器之間,服務器暴露使用註冊表

  1. 客戶端獲得服務器從RMI註冊存根的存根
  2. 然後客戶端將其作爲觀察者存根到服務器的addObserver方法
  3. 服務器通知使用此存根的客戶端

下面的代碼將給出一個更好的主意

import java.rmi.*; 
import java.rmi.registry.*; 
import java.rmi.server.*; 
import java.util.Observable; 
import java.util.Observer; 
import java.net.*; 

import javax.rmi.ssl.SslRMIClientSocketFactory; 
import javax.rmi.ssl.SslRMIServerSocketFactory; 

interface ReceiveMessageInterface extends Remote 
{ 
    /** 
    * @param x 
    * @throws RemoteException 
    */ 
    void receiveMessage(String x) throws RemoteException; 

    /** 
    * @param observer 
    * @throws RemoteException 
    */ 
    void addObserver(Remote observer) throws RemoteException; 
} 

/** 
* 
*/ 
class RmiClient extends UnicastRemoteObject 
{ 
    /** 
    * @param args 
    */ 
    static public void main(String args[]) 
    { 
     ReceiveMessageInterface rmiServer; 
     Registry registry; 
     String serverAddress = args[0]; 
     String serverPort = args[1]; 
     String text = args[2]; 
     System.out.println("sending " + text + " to " + serverAddress + ":" + serverPort); 
     try 
     { // Get the server's stub 
      registry = LocateRegistry.getRegistry(serverAddress, (new Integer(serverPort)).intValue()); 
      rmiServer = (ReceiveMessageInterface) (registry.lookup("rmiServer")); 

      // RMI client will give a stub of itself to the server 
      Remote aRemoteObj = (Remote) UnicastRemoteObject.exportObject(new RmiClient(), 0); 
      rmiServer.addObserver(aRemoteObj); 

      // call the remote method 
      rmiServer.receiveMessage(text); 
      // update method will be notified 
     } 
     catch (RemoteException e) 
     { 
      e.printStackTrace(); 
     } 
     catch (NotBoundException e) 
     { 
      System.err.println(e); 
     } 
    } 

    public void update(String a) throws RemoteException 
    { 
     // update should take some serializable object as param NOT Observable 
     // and Object 
     // Server callsbacks here 
    } 
} 

/** 
* 
*/ 
class RmiServer extends Observable implements ReceiveMessageInterface 
{ 
    String address; 
    Registry registry; 

    /** 
    * {@inheritDoc} 
    */ 
    public void receiveMessage(String x) throws RemoteException 
    { 
     System.out.println(x); 
     setChanged(); 
     notifyObservers(x + "invoked me"); 
    } 

    /** 
    * {@inheritDoc} 
    */ 
    public void addObserver(final Remote observer) throws RemoteException 
    { 
     // This is where you plug in client's stub 
     super.addObserver(new Observer() 
     { 
      @Override 
      public void update(Observable o, 
       Object arg) 
      { 
       try 
       { 
        ((RmiClient) observer).update((String) arg); 
       } 
       catch (RemoteException e) 
       { 

       } 
      } 
     }); 
    } 

    /** 
    * @throws RemoteException 
    */ 
    public RmiServer() throws RemoteException 
    { 
     try 
     { 
      address = (InetAddress.getLocalHost()).toString(); 
     } 
     catch (Exception e) 
     { 
      System.out.println("can't get inet address."); 
     } 
     int port = 3232; 
     System.out.println("this address=" + address + ",port=" + port); 
     try 
     { 
      registry = LocateRegistry.createRegistry(port); 
      registry.rebind("rmiServer", this); 
     } 
     catch (RemoteException e) 
     { 
      System.out.println("remote exception" + e); 
     } 
    } 

    /** 
    * 
    * @param args 
    */ 
    static public void main(String args[]) 
    { 
     try 
     { 
      RmiServer server = new RmiServer(); 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
      System.exit(1); 
     } 
    } 
}