EJB的使用 - 何时使用远程和/或本地接口?

189
我对Java EE非常陌生,正在试图理解本地接口和远程接口的概念。我被告知Java EE的一个重要优势是易于扩展(我认为这意味着可以在不同的服务器上部署不同的组件)。那么远程和本地接口是在哪里发挥作用的?如果您的应用程序希望在不同的服务器上拥有不同的组件,您是否应该使用远程接口?如果您的应用程序只会驻留在一个服务器上,那么使用本地接口是否更合适?
如果我的上述假设是正确的,那么如何选择在新应用程序中使用本地接口还是远程接口,特别是当您不确定流量的数量时?可以首先使用本地接口,然后根据需要逐渐升级为远程接口吗?
感谢任何澄清和建议。
4个回答

191
我很新于Java EE,正在尝试理解本地接口和远程接口的概念。
在EJB规范的最初版本中,EJB被“假定”为远程组件,唯一调用它们的方式是进行远程调用,使用RMI语义并带有所有相关开销(每个方法调用都需要进行网络调用和对象序列化)。即使在与EJB容器同一虚拟机中的情况下,EJB客户端也必须支付这个性能惩罚。
后来,Sun意识到大多数业务应用实际上并没有将EJB分布在不同层,并通过引入本地接口的概念修复了规范(在EJB 2.0中),以便于在与EJB容器同一虚拟机中的客户端可以使用直接方法调用调用EJB,完全绕过RMI语义(及其相关开销)。
我被告知Java EE的一个重要优势是易扩展(我相信这意味着可以在不同服务器上部署不同的组件)。
Java EE可以进行扩展,但这并不一定意味着分发组件。您可以在集群中运行Web+EJB应用程序,而无需分离Web层和EJB层。
如果您的应用程序位于单个服务器上,则应该使用本地接口,如果您的应用程序预计在不同服务器上具有不同的组件,则应该使用远程接口吗?
我会这样表达:如果客户端不在同一JVM中,请使用远程接口(这并不意味着仅使用一个服务器/JVM)。
我可能会从使用本地接口开始。正如先前暗示的那样,切换到远程接口并非始终是强制性的(您可以集群“collocated”结构)。
我建议查看下面提到的资源(前两个资源非常古老但仍然相关,后两个资源比较新)。
资源
  • 深入解析J2EE集群技术 by 王宇
  • Java EE应用程序的扩展性设计 by 王宇
  • Java EE应用程序的扩展性设计--第二部分 by 王宇

  • 3
    我觉得这个问题很有趣。你所说的“切换到远程接口不是绝对必要”的意思是什么?这是否意味着当你在同一JVM之外添加一个新客户端时,你不需要创建一个远程接口? - mohamida
    3
    @Josek 谢谢,很高兴你喜欢它。 @mohamida 我稍微改了措辞。我的意思是您可以对一个共现结构进行聚类。 - Pascal Thivent
    2
    感谢您的回答和额外提供的资源,它们非常有帮助。看起来有几种方法可以扩展Web应用程序...即分发组件(我理解为将不同层分配到不同的JVM上?)或使用负载均衡(这将在多个服务器上拥有整个应用程序?),我想您可以同时使用两者的组合?您是否知道关于这个主题的好书?再次感谢! - Brian DiCasa
    3
    “似乎有几种方法可以扩展Web应用程序(…)我想你可以同时使用两种方法?”是的,确实如此。“你是否碰巧知道这个主题的好书?”遗憾的是,我不知道是否有“绝对资源”,但我已添加了更多资源和一些参考资料。 - Pascal Thivent
    第一个资源链接已失效。 - Viacheslav Dobromyslov

    49

    虽然我认同以上大部分内容,但我希望对“如何开始”这一点做出一些细化建议。

    我的建议是:在代码中永远不要直接编程到EJB接口,而是使用一个常规的、面向业务的接口,并针对它进行编程(也就是说,让你的代码调用面向业务的接口上的方法),并提供EJB “粘合”代码作为可插拔实现。你的程序应该专注于业务逻辑,而不是像EJB这样的实现细节。

    这样,你可以轻松地在远程和本地实现之间切换——如果你使用Spring这样的IoC容器,你可以仅通过配置来完成。

    关于从本地切换到远程的特别说明:请注意,两者之间存在一些语义上的差异。例如,通过“远程接口”调用EJB方法会导致参数按值传递,而通过“本地接口”调用则按引用传递。这是一个重大的差异;所以如果你“从本地开始”,确保你的系统设计考虑了“远程”的语义。

    如果你的设计依赖于EJB方法更改传入对象,那么你以后“转换到远程”可能会很棘手;甚至可能不可能。

    祝你好运。


    2
    听起来又是一个减少可变性的原因,符合Effective Java的建议。这是否有助于灵活地将RMI类型接口切换到远程EJB? - Thufir

    25
    根据EJB规范3.2,EJB可以是本地的或远程的。业务接口不能同时既是本地的又是远程的。
    @Local 注释的 Bean 只能在同一个应用程序中被访问。
    @Remote 注释的 Bean 可以跨不同的应用程序、不同的 JVM 或应用服务器进行访问。
    因此需要记住以下重要事项:
    1. 如果一个 Bean 类包含 @Remote 注释,则所有已实现的接口都必须是远程的。
    2. 如果一个 Bean 类没有注释或指定了 @Local 注释,则假定所有已实现的接口都是本地的。
    3. 对于一个没有接口的 Bean 显式定义的任何接口必须声明为 @Local。
    4. EJB 3.2 版本倾向于提供更多的细粒度控制,以便明确定义本地和远程接口的情况。

    1
    问题:您能否使用“@Local”在另一个应用程序(JAR、WAR、EAR),但同一JVM中调用EJB? - Carlitos Way
    @PritamBanerjee 你有关于Carlitos Wa的任何想法吗?我也遇到了同样的问题。EJB在不同的集群中,客户端servlet应用程序在另一个集群中。 - Govinda Sakhare
    @GovindaSakhare 我不太确定。对不起 :( - Pritam Banerjee

    7
    这可能回答了您的疑虑:
    通常情况下,当您计划在分布式环境中使用bean时,您的企业Java Bean将需要远程客户端视图。具体来说,这些情况是指将使用bean的客户端位于不同的Java虚拟机(JVM)中的情况。对于远程客户端视图,通过远程方法调用(RMI)处理从远程主页接口和/或远程组件接口调用的任何方法。
    只有在确保其他企业bean或客户端仅在单个JVM中访问bean时,EJB才能使用本地客户端视图。如果是这种情况,则此类访问将通过直接方法调用而不是RMI进行。
    来源:http://www.onjava.com/pub/a/onjava/2004/11/03/localremote.html?page=last&x-showcontent=text

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接