1

RMI を介して通信する 2 つのアプリケーション、スレーブ サーバー (そのうち複数あります) とマスター サーバーがあります。

優れた抽象設計に従って、マスターと通信するときに RMI を使用していることをスレーブが認識しないようにスレーブを実装したいと思います (たとえば、2 つのアプリを同じ JVM 内で実行できるようにするため)。 :

public static void main(String[] a) {
     Master ms = magicGetTheMasterFromRMI();
     new Slave(ms);
}

...

class Slave {

   public Slave(Master m) {
       m.registerSlave(this); // PROBLEM LINE   
   }

}

問題: 上記の行はPROBLEM LINE機能しません。単純にこれを渡すことができないためです (それSlave自体は、応答する aです)。明示的に行う必要があります(または以前にエクスポートした場合) が、それによってクラスが RMI に依存し、設計が壊れます。RemoteMasterUnicastRemoteObject.exportObject(this, 0)toStub(this)Slave

さらに、RMI 依存関係も追加registerSlaveする catch を強制します。RemoteException

これらの問題を解決するために何を提案しますか?

(また、これらのクラスが Remote を実装しなければならないことにも悩まされていますが、抽象化でしか実現できないと思います)

4

4 に答える 4

1

RMIにはオブジェクトの明示的なエクスポートが必要です

UnicastRemoteObjectまたはActivatableを拡張しない場合のみ。もしそうなら、それらは建設時に自動輸出されます。

UnicastRemoteObject.exportObject(this、0)を明示的に実行する必要があります

いいえ、上記を参照してください。

(または以前にエクスポートされた場合はtoStub(this))

toStub()が何であれ。RemoteObject.toStub()がありますが、それを呼び出すことはできません。もしあなたがそうなら、あなたはあなたの時間を無駄にしています。

しかし、それを行う必要はまったくありません。'this'がエクスポートされたリモートオブジェクトの場合、RMIパラメータまたは結果として渡すことができます。RMIはスタブを自動的に置き換えます。

于 2010-10-12T05:41:33.383 に答える
1

さて、私はこのようにしました:

interface Service {
   void doIt();
}

class ServiceImpl implements Service {
  public void doIt() { ... }
}

interface RemoteService extends Remote {
  void proxyDoIt() throws RemoteException;
}

class RemoteServiceHost implements RemoteService {
  public void proxyDoIt() throws RemoteException {
    // serviceImpl is a field, defined in the constructor
    serviceImpl.doIt();
  }
}

class RemoteServiceClient implements Service {
  public void doIt() {
   try {
    // remoteService is a field, defined in the constructor
    remoteService.proxyDoIt();
   } catch (RemoteException e) {
    throw new RuntimeException(e);
   }
  }
}
于 2010-09-22T08:53:59.407 に答える
0

スレーブ アプリケーションの一部は、RMI を介して呼び出しを受信し、RemoteException などを処理する準備をする必要があります。通信を仲介し、RMI とローカルの問題を隠す、スレーブとマスターの間に何らかのプロキシを導入しないでください。 . たとえば、次の行に沿って:

public Slave(Master m)
{
   new MasterConnection(m, this);
}

class MasterConnection implements Slave extends UnicastRemoteObject
{
   Slave s;

   public MasterConnection(Master m, Slave s) throws IOException
   {
      this.slave = s;
      try {
         exportObject(this);
      } catch (RemoteException e){
         throw new IOException("Could not communicate with Master etc....");
      }
      master.registerSlave(this);
   }

   public void callbackFromMaster(Object arg) // or whatever
   {
      s.callbackFromMaster(arg);
   }
}
于 2010-09-23T15:39:08.393 に答える
0

この抽象化には注意が必要です。リモートで処理されるリクエストは、ローカルで処理されるリクエストとは多くの点で異なります。遅延、障害モード、再試行のセマンティクスなどです。

実際には有効ではないため、抽象化が漏れている可能性があります。

于 2010-09-15T13:46:27.867 に答える