سؤال

لديّ تطبيقان يتواصلان عبر RMI ، خادم عبيد (سيكون هناك متعددة) وخادم رئيسي.

بعد تصميم تجريدي جيد ، أود تنفيذ العبد بطريقة لا تعرف أنه عند التحدث إلى السيد ، فإنه يستخدم RMI (بحيث يمكن أيضًا تشغيل التطبيقان داخل نفس 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 نفسها هي Remote أيّ Master سوف نتحدث مرة أخرى). يجب أن أفعل صراحة UnicastRemoteObject.exportObject(this, 0) (أو toStub(this) إذا تم تصديره في وقت سابق) ولكن هذا يجعل Slave الفئة تعتمد على RMI ، كسر التصميم.

بالإضافة إلى ذلك، registerSlave يجبرني على التقاط RemoteException, والتي تضيف أيضا التبعية RMI.

ماذا تقترح حل هذه القضايا؟

(يزعجني أيضًا أن هذه الفئات يجب أن تنفذ عن بُعد ، لكن أعتقد أنه لا يمكننا الذهاب إلى أبعد من ذلك مع التجريد)

هل كانت مفيدة؟

المحلول

حسنًا ، لقد فعلت ذلك مثل هذا:

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);
   }
  }
}

نصائح أخرى

RMI يحتاج إلى تصدير صريح للكائنات

فقط إذا لم يتم تمديد UnicastRemoteObject أو Activatable. إذا فعلوا ذلك ، فسيتم تصديرهم تلقائيًا على البناء.

لا بد لي من القيام بوضوح unicastremoteObject.exportObject (هذا ، 0)

لا ، انظر أعلاه.

(أو Tostub (هذا) إذا تم تصديره في وقت سابق)

مهما كان Tostub (). هناك remoteObject.tostub () ، لكن لا يمكنك الاتصال بذلك ، وإذا كنت تضيع وقتك.

لكن ليس عليك القيام بذلك على الإطلاق. إذا كان "هذا" كائنًا عن بُعد تم تصديره ، فيمكنك فقط تمريره كمعلمة أو نتيجة RMI. سوف RMI استبدال الكعب تلقائيا.

سأكون حذرًا من هذا التجريد - تختلف طلبات الخدمة عن بُعد عن الطلبات التي يتم تقديمها محليًا بعدة طرق - الكمون ، أوضاع الفشل ، ودلالات إعادة المحاولة.

قد يكون التجريد الخاص بك متسربة لأنه غير صالح حقًا.

يجب أن تكون جزءًا من تطبيق الرقيق الخاص بك مستعدًا لتلقي المكالمة عبر RMI ، والتعامل مع RemoteException ، وما إلى ذلك. لماذا لا تقدم وكيلًا من نوع ما بين العبد والسيد الذي يتوسط في التواصل ويخفي RMI vs Proced . على سبيل المثال ، على غرار:

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);
   }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top