【问题标题】:Java RMI - UnicastRemoteObject: what is the difference between UnicastRemoteObject.exportObject() and extends UnicastRemoteObject?Java RMI - UnicastRemoteObject:UnicastRemoteObject.exportObject() 和扩展 UnicastRemoteObject 有什么区别?
【发布时间】:2011-01-12 18:56:16
【问题描述】:

我正在准备考试,我有一个问题希望有人能回答我。

这是关于 RMI 和远程对象的。我想知道为什么这两种实现之间存在如此大的差异。一个是扩展 UnicastRemoteObject,而另一个是将对象导出为 UnicastRemoteObject。

我真的不明白

界面:

public interface EchoI extends Remote {
   public String echo() throws RemoteException
}

这是服务器代码(版本 1):

public class EchoImpl extends UnicastRemoteObject implements EchoI {
    public EchoImpl {
        super();
    }

    public static void main (String[] args) {
        try {
            LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
            StoreHouse storehouseImpl = new StorehouseImpl();
            Naming.rebind("//localhost/StoreHouse.SERVICE_NAME", storehouseImpl);
            System.out.println("Server ready");
        } catch (RemoteException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }

    public String echo() {
        return "echo";
    }
}

这将是第 2 版:

public class EchoImpl implements EchoI {
    public static void main (String[] args) {
        EchoI echoService = new EchoImpl();
        EchoI stub = (EchoI) UnicastRemoteObject.exportObject(echoService, 0);
        Registry registry = LocateRegistry.getRegistry();
        registry.bind("echoService", stub);
        ...
    }
}

我的问题是:这两者有什么区别?

在第一个版本中,注册表是显式创建的,此外,远程对象是在重新绑定中创建的?

我真的很好奇,为什么一开始我需要自己创建注册表,但不需要显式导出对象,只需使用Naming 重新绑定它。该对象之前是否已经绑定到注册表,或者我可以使用 bind 代替?如果对象之前没有绑定并且执行了重新绑定,会发生什么情况?

在第二个版本中,注册表似乎已经创建。 为什么绑定到命名和直接绑定到注册表一样?

这就是我的想法:

  • 第一个类直接实现了 UnicastRemoteObject 接口,这意味着在运行时创建注册表并将对象自动导出到 RMI 注册表。
  • 由于对象已绑定到注册表,因此必须进行重新绑定而不是正常绑定。
  • 后者明确地做了这一切。

【问题讨论】:

    标签: java interface export rmi


    【解决方案1】:

    这里有两个问题。

    1. 您可以扩展UnicastRemoteObject 或致电UnicastRemoteObject.exportObject().,具体由您决定。第一个是简单和自动的;第二个意味着你可以扩展另一个类。

    2. 您可以使用外部 RMI 注册表,也可以在服务器 JVM 中自行创建。再次,你做什么取决于你,这两种方式都有好处。

      这两个问题没有交互作用。

    3. 如果您使用extend UnicastRemoteObject,您还可以获得hashCode()equals() 方法的“远程语义”的好处,这样所有存根似乎都与导出它们的远程对象相同,但这在客户端没有实际用途,实际上只是为了支持 RMI 实现本身。

    【讨论】:

      【解决方案2】:

      java.rmi.server.UnicastRemoteObject 用于使用 Java 远程方法协议 (JRMP) 导出远程对象并获取与远程对象通信的存根。

      对于下面的构造函数和静态exportObject方法,获取正在导出的远程对象的存根...

      你应该关注Javadoc

      【讨论】:

      • 顺便说一句,你的服务器代码版本 1 让我感到困惑,locateRegistry 无法工作,因为它没有被声明
      • 感谢您的回复,但它并没有真正让我明白……您是否更喜欢现在的代码?
      • ;-) 现在编译器更喜欢您的代码,结果与在 RMI 注册表中以提供的名称注册的对象相同并且客户端可以访问该对象。唯一的区别是 rebind 比 bind 更容错(如果已经绑定)。我会支持你的问题以吸引更多人
      • 再次感谢 - 所以第一个版本更安全,对吧?在几乎所有教程中,RMI 对象都以后一种方式导出,但 IMO 我更喜欢第一个版本而不是另一个版本......
      • 如前所述,它们是等效的,不同之处在于重新绑定不会抛出 AlreadBoundExeption,我也更喜欢您的第一个选项。在你的考试中,你可以描述一种方式并提到还有另一种选择。
      【解决方案3】:

      在需要扩展任何其他类的情况下,您可以调用UnicastRemoteObject.exportObject() 而不是扩展UnicastRemoteObject。总体效果和我想的一样。

      See this

      【讨论】:

      • 链接质量差,至少有两个主要错误。 -1
      【解决方案4】:

      首先,使用Naming 类和Registry 类绑定和重新绑定远程对象与类是否扩展UnicastRemoteObject 的场景无关。有关差异,请参阅here

      其次,扩展UnicastRemoteObject 的类之间的区别在于,如果将该类型的对象用作存根,那么您将不再需要调用UnicastRemoteObject.exportObject 来获取存根以与注册表绑定。在您的版本 1 中,StorehouseImpl 必须扩展了 UnicastRemoteObject,实际上,对于您的版本 1,EchoImpl 没有必要扩展 UnicastRemoteObject,因为没有 EchoImpl 的实例被注册为远程对象到注册表。

      第三,你提到如果rebind 在没有bind 事先执行的情况下执行会发生什么。如 javadoc here 中所述,如果未插入任何键名,则其行为方式与第一次执行 bind 时相同。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-12
        • 1970-01-01
        • 2012-08-11
        • 1970-01-01
        • 2018-03-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多