2009-07-27 42 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); 
     } 
    } 
}