将EJB打包在JavaEE 6 WAR与EAR中的区别

29

开始一个新项目,想知道将EJB打包在WAR与EAR中的优缺点。当EJB位于WAR时,JNDI是否仍然有效?效率如何?等等。

谢谢。

5个回答

58
将EJB bean放置在单独的JAR文件中的一个重要动机是实现传统意义上的业务逻辑视图逻辑的分离。
由于EJB bean应当专注于业务逻辑,因此将它们放入单独的模块中是很有道理的。
这正是传统Java Enterprise Archive所促进的。EJB bean被放入代表EJB模块的JAR文件中,而与Web相关的工件(Facelets、Backing Bean、实用代码)则被放入代表Web模块的Web Archive(WAR)文件中。请注意,WAR实际上不一定是文件,在所谓的展开格式中,它们只是目录。
这种分离的关键方面是这两个模块通过类装载器层次结构进行隔离。Web模块可以访问EJB模块中的资源(通常是bean),而EJB模块可以引用整个EAR框架中定义的资源(通常是库)。另一个方向是不可能的。特别是,EJB模块无法访问Web模块中定义的任何资源。
这种执行是故意的。 业务逻辑应该完全独立于任何视图技术。强制执行此隔离可以防止开发人员在意外或在压力下混淆这些问题。这种分离的好处是业务逻辑可以轻松地被Java SE客户端、Web模块客户端、JAX-RS客户端等使用。如果业务逻辑意外具有JSF或Servlet依赖关系,那么从Java SE客户端使用它将非常困难。
将此与Facelets不允许使用脚本标签进行比较。这使得Facelets保持清晰,并让它们专注于组件布局和标记语言。另一个类比是编写接口,这将契约与实现分离。
因此,拥有单独的EJB模块实际上是一种最佳实践。然而...

对于较小的项目来说,没有必要进行这种分离,对于初学者来说,在理解需要放置在何处的结构方面可能会比较困难。因此,取消强制性分离可以让经验不足的开发人员更容易地开始使用Java EE。这为他们提供了一个温和的介绍,让他们更好地了解Java EE。一旦他们掌握了分层的概念,他们可以选择引入 EJB 模块


那我可以在一个打包成WAR文件的应用程序中使用所有Java EE技术吗? - Martin Andersson
1
@MartinAndersson,确实几乎所有的都可以。一些奇特的东西仍然需要单独部署或作为EAR的一部分,例如应用程序客户端容器或(稍微不那么奇特的)JCA资源适配器。但是所有“正常”的东西,如CDI、EJB、JPA、JMS、JASPIC等都可以打包在WAR文件中。 - Arjan Tijms
你可以分离EJB JAR并将其放置在WEB-INF/lib目录下,对吗? - Kalpesh Soni
在Java EE 5中,你不能在WAR中部署EJBs。 - Eduardo Dennis
十年后,我会说我认为人们应该使用WAR打包。我们可以使用常见的约定和勤奋来实现适当的设计分离,就像大多数其他框架一样。JPA实体不应调用EJB方法,EJB方法不应调用JSF bean:我不需要EAR文件来强制执行此操作。此外,我还没有参与过真正重用业务逻辑的项目,我认为在预期“有一天我们会需要它”的情况下复杂化设计并不是一个好主意——通常那一天永远不会到来。 - DavidS

6

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

WAR 中的 EJB

优点:

  1. 开发和部署更简单

  2. 您可以使用 @Path 注释将会话 Bean 方法公开为 REST 服务。请参见 此处

缺点:

  1. 不支持 JNDI 查找,因此我认为您无法从另一个应用程序客户端执行 RMI

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


1
尽管规范不要求将WAR中的EJB设置为远程可访问,但JBoss7和WebLogic12c都允许您从独立的Java客户端访问它们。因此,JNDI查找和调用可以从远程客户端工作。 - Raylite3

5

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

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

希望对你有所帮助。


这就是我想知道的,当EJB打包在EAR中(在自己的EJB jar中分开)时,所有可用的服务是否仍然可用于将EJB打包在WAR中。到目前为止,我知道您无法进行JNDI查找。 - duvo

5

我目前正在学习EJB 3.1认证指南,并需要测试其每个功能。而且当使用war时,所有功能都可用。

EJB Lite与WAR包装非常不同。

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


1
我对这个主题进行了一些实验,并对结果感到惊讶。我的结论是不要在WAR中使用EJB。让EJB容器来完成这项工作,这样任何人都可以使用EAR来获得最佳和无误的开发。
当我使用NetBeans 7.1.3、Glassfish 3.1.2.2和JRebel进行EJB开发时,我意识到如果它被部署在EAR包中,JRebel只能完美地重新加载EJB模块中所做的更改。如果我制作简单的WAR包,类加载器在开发阶段表现出非常奇怪的方式,并导致了很多随机错误。
无论如何,在正常部署的WAR包中工作得很好,正如其他人所提到的那样。
此外,在WAR包中,保存和编译后NamedQuery字符串的更改不会出现。如果我打包成EAR,开发就会变得顺畅而快速。当然,这也可能是JRebel中的一个错误。

1
实际上,你的问题似乎与JRebel有关。 - gouessej

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