在 JavaEE 6 WAR 与 EAR 中打包 EJB

Posted

技术标签:

【中文标题】在 JavaEE 6 WAR 与 EAR 中打包 EJB【英文标题】:Packaging EJB in JavaEE 6 WAR vs EAR 【发布时间】:2011-05-25 09:11:57 【问题描述】:

开始一个新项目,想了解在 WAR 与 EAR 中打包 EJB 的优缺点。

当 EJB 处于 WAR 中时,JNDI 是否仍然有效?效率?等等?

谢谢。

【问题讨论】:

【参考方案1】:

在单独的 JAR 中包含 EJB bean 的一个重要动机是业务逻辑视图逻辑的古老分离。

由于 EJB 应该只专注于业务逻辑,因此将它们放入单独的模块中是有意义的。

这正是传统 Java Enterprise Archive 所促成的。 EJB bean 进入一个代表EJB module 的 JAR 文件,而与 Web 相关的工件(Facelets、支持 bean、实用程序代码)进入一个代表 Web module 的 Web 存档 (WAR) 文件。请注意,WAR 实际上不一定是文件。在所谓的分解格式中,它们只是目录。

这种分离的一个关键方面是这两个模块通过类加载器层次结构隔离Web module 可以访问来自EJB module 的资源(通常是bean),EJB module 可以引用整个EAR 保护伞中定义的资源(通常是库)。另一个方向是不可能的。具体来说,EJB module 无法访问Web module 中定义的任何资源。

这种强制执行是故意的。

业务逻辑应该完全独立于任何视图技术。强制执行这种隔离可以防止开发人员意外或在压力下混合这些问题。这种分离的好处是业务逻辑可以很容易地被 Java SE 客户端、Web 模块客户端、JAX-RS 客户端等使用。如果业务逻辑不小心具有 JSF 或 Servlet 依赖项,则很难使用它来自 Java SE 客户端。

将此与 Facelets 不允许使用 scriptlet 进行比较。这使 Facelets 保持干净,让它们专注于组件布局和标记。另一个类比是对接口的编码,它将合同与实现分开。

因此,拥有一个单独的 EJB 模块实际上是一种最佳实践。不过……

对于较小的项目,可能没有必要进行这种分离,而对于初学者来说,他们可能很难理解需要去哪里的结构。因此,取消强制分离使没有经验的开发人员更容易开始使用 Java EE。它为他们提供了对 Java EE 的温和介绍,之后他们获得分层的想法后,他们就可以选择引入EJB module

【讨论】:

所以我可以在打包在 WAR 文件中的应用程序中使用 所有 Java EE 技术? @MartinAndersson 几乎都是这样。一些奇特的东西仍然必须单独部署或作为 EAR 的一部分部署,例如应用程序客户端容器或(不那么奇特)JCA 资源适配器。但是所有“正常”的东西,如 CDI、EJB、JPA、JMS、JASPIC 等都可以打包在 WAR 文件中。 你可以进行分离并且仍然将ejb jar放在web inf / lib中正确吗? 你不能在 java ee 5 中部署 ejbs 十年后我会说我认为人们应该使用WAR包装。我们可以使用常见的约定和勤奋来实现适当的设计分离,就像大多数其他框架一样。 JPA 实体不应该调用 EJB 方法,EJB 方法也不应该调用 JSF bean:我不需要 EAR 文件来强制执行此操作。此外,我还没有从事一个真正重用业务逻辑的项目,而且我认为在预期“有一天我们会需要它”的情况下使设计复杂化并不是一个好主意——通常那一天永远不会到来。 【参考方案2】:

我对这个主题做了一些实验,结果让我感到非常惊讶。我的结论是永远不会在 WAR 中使用 EJB。让我们把工作留给 EJB 容器,所以如果有人想要获得最佳且无错误的开发,请改用 EAR。

当我使用 NetBeans 7.1.3、Glassfish 3.1.2.2 和 JRebel 在 WAR 中使用 EJB 以加快开发速度时,我意识到 JRebel 只有在将 EJB 模块中的更改部署在 EAR 包中时才能完美运行。如果我制作了简单的 WAR 包,那么类加载器在开发阶段的表现绝对很奇怪,并导致了很多随机错误。

无论如何,正常部署中的war包就像其他人所说的那样完美。

同样在 WAR 包中,NamedQuery 字符串的更改在保存和编译后不会出现。如果我将其打包到 EAR 中,则开发是顺利且快速的。当然,这也可能是 JRebel 中的一个错误。

【讨论】:

【参考方案3】:

我目前正在研究一些 EJB 3.1 认证指南,并且必须测试它的每个功能。并且在使用战争时都可以使用。

EJB Lite 与 WAR 打包非常不同。

您可以使用可以包含在 Web 项目中的 ejb jar 来获得一些逻辑模块化。但是所有模块共享相同的环境 (jndi),因此可能会发生一些名称冲突。在 EAR 项目中,每个模块都有自己的命名空间。

【讨论】:

【参考方案4】:

到目前为止,这是我得到的。

WAR 中的 EJB

优点:

    开发和部署更简单

    您可以使用 @Path 注释将会话 Bean 方法公开为 REST 服务。见here

缺点:

    不支持 JNDI 查找,所以我相信你不能从另一个应用程序客户端执行 RMI

    正如 arjan 指出的那样,它在设计上缺乏模块化。

【讨论】:

虽然规范不要求 WAR 中的 EJB 可以远程访问,但 JBoss7 和 WebLogic12c 都允许您从独立的 Java 客户端访问它们。所以 JNDI 查找和调用确实可以从远程客户端工作。【参考方案5】:

我认为您需要记住的是,WAR 中的 EJB 是 EJB Lite 的一部分,这是使应用程序以 EJB 容器提供的最少服务运行的一个很好的努力。因为您并不总是需要 EJB 容器提供的所有服务。

因此,如果您想知道将 EJB 打包到 WAR 或 EAR 中的利弊,那么您应该考虑一下您需要多少服务。

HTH。

【讨论】:

这就是我想知道的,当 EJB 被打包在 EAR 中时所有可用的服务(在它自己的 EJB jar 中单独)在 EJB 被打包在 WAR 中时仍然可用。到目前为止,我知道您不能进行 JNDI 查找。

以上是关于在 JavaEE 6 WAR 与 EAR 中打包 EJB的主要内容,如果未能解决你的问题,请参考以下文章

关于war包 jar包 ear包 及打包方法

java的war、jar、ear包的作用分别是啥?

如何使用 Maven 在 EAR 中添加 WAR

关于war包 jar包 ear包 及打包方法

如何在 EAR 或 WAR 之外存储 Java EE 配置参数?

是否必须在EAR中的WAR中重复使用常见的JAR?