JSF2 - 由 EJB 或 ManagedBean 支持?

Posted

技术标签:

【中文标题】JSF2 - 由 EJB 或 ManagedBean 支持?【英文标题】:JSF2 - backed by EJB or ManagedBean? 【发布时间】:2011-01-26 14:37:19 【问题描述】:

在学习 JSF2 时,我意识到我不确定支持组件应该是什么。从设计的角度来看,EJB 和@ManagedBeans 有什么区别?

最后我要使用JPA,所以EJB是业务层的自然选择。直接从 JSF 使用 EJB 是一种好习惯(如 here 所述)吗?

目前我倾向于将@ManagedBeans 用于不需要访问业务层(例如视图助手)或处理请求/会话数据的组件。用于其他目的,例如在网格中列出一些东西,我会直接访问 EJB。

这是一个好的设计吗?为了干净的层分离,我是否应该对所有支持 bean 使用@ManagedBeans,即使在某些情况下它们只委托给 EJB?

【问题讨论】:

【参考方案1】:

通过从 Xhtml 调用 EJB,您在视图和业务层的实现选择之间引入了紧密耦合。

如果您使用托管 bean 来调用 EJB,[或者甚至放入业务委托],您将能够将您的业务层完全更改为 Spring,而不会影响视图层 (XHTML)。

这在技术上是可行的,并且很容易让您(JSR 299)能够使用 EJB 作为您的托管 bean,而这可能是这些供应商希望您做的 - 专注于细节。但这是否是正确的做法? - 没有。

【讨论】:

如何将 EJB 注入到 ManagedBean?【参考方案2】:

在 Java EE 6 中,各种托管 bean 之间存在一些重叠:JSF 托管 bean (@ManagedBean)、CDI 托管 bean (@Named) 和 EJB bean(@Stateless、@Statefull、@Singleton)。

在视图层中,我看不出坚持使用@ManagedBean 有什么特别的优势。 CDI 变体 @Named 似乎能够做同样的事情,甚至更多,例如为您提供转换范围的访问权限。

目前的想法似乎是最终 EJB 组件模型也将被改造为一组 CDI 注释。尤其是专家组成员 Reza Rahman 经常暗示这一点。参见例如Dependency Injection in Java EE 6 - Part 1

目前这还没有发生,所以 EJB bean 仍然是最容易放置业务逻辑的地方,尤其是当 JPA 用于持久性时。

尽管如此,无论 CDI 是否会获得 EJB 的功能,恕我直言,为“支持 bean”概念使用单独的 bean 并为“业务逻辑”使用单独的 bean 仍然是最佳实践。

支持 bean 可以非常纤细,只包含一些对模型对象和服务 (EJB) 的引用。支持 bean 的操作方法几乎可以直接委托给服务,但它们的附加价值在于为用户提供反馈(在成功或失败时添加 FacesMessages)和进行小的 UI 修改(例如,将布尔值设置为 false 以显示一些对话框) .

服务(业务逻辑)不应该知道任何特定的表示。它们应该同样适用于 JSF 支持 bean、JAX-RS、Servlet、独立的 Java SE 远程客户端或其他任何东西。

即使所有 bean 都将成为 CDI bean,那么这也不会改变这种基本的职责分工。

【讨论】:

附注David Geary 和 Cay Horstmann 提到了以下内容:“对于可以在 JSF 页面中使用的 bean,有两种独立的机制,CDI bean 和 JSF 托管 bean,这是一个历史性的意外。我们建议您使用 CDI bean,除非您的应用程序必须在普通的 servlet 运行程序上运行,例如 Tomcat”(参见核心 JavaServer Faces,第 40 页)【参考方案3】:

非常有效的问题,但我想答案取决于您的项目方法的“严格性”。 JSF 支持 bean 和 EJB 之间确实存在一些冗余,因为它们都实现了一些业务逻辑。

在一个理想的 JSF 功能使用中,convertersrenderedvalidator 等。支持 bean可以确实是干净的业务逻辑代码。但在实践中,一些与表示相关的逻辑经常在其中泄漏。

这个与表示相关的逻辑理想情况下不应该在 EJB 中。这种表示相关的逻辑可能依赖于 faces 包,但不是必需的。正是它所做的 决定了它是否与演示相关。

不过,统一的组件模型有一些优势。这是Seam 和Spring 采用的方法。在这两种情况下,具有声明式事务等的业务组件都可以直接在 JSF 中使用(Spring 不使用 EJB,但提供了类似的模型)。然而,EJB 纯粹主义者会说您应该将两者分开。

所以对我来说,这最终是一个项目的品味和规模的问题。我可以想象,对于在 JSF 中使用 EJB 的中小型项目来说效果很好。对于这种严格性至关重要的大型项目,请确保不要拧紧层。

【讨论】:

谢谢,它确实提供了一些启示。实际上,我已经了解 Spring 并想尝试使用 Sun 堆栈进行更改。我试图区分这两种 bean 类型。我不想在 EJB 和 ManagedBeans 之间混合逻辑,所以我正在考虑将 ManagedBeans 仅视为视图助手/入口点,并在 EJB 中执行所有逻辑。对于此类问题,统一模型确实有一些优势。 我觉得这个答案更有启发性。尽管如此,还有很多东西要学。 从 JSF 2.2 开始,您将希望使用 CDI 而不是 @ManagedBean,这需要稍作修改以使 bean 成为 @Named 并更改范围。 EJB 提供了一些很棒的功能,您想成为多“纯粹”的人取决于您。我一般不介意在我的页面上使用 EJB。【参考方案4】:

有趣的文章,不知道。然而,对我来说,这篇文章更像是对 JSF 托管 bean 的咆哮。它还将 EJB 与 JSF 紧密耦合在一起。这在小型(个人)应用程序中可能很有趣,但在您希望完全控制所服务的 EJB 的现实世界 SOA 应用程序中可能并不有趣。

至于哪一个用于什么,我会坚持使用@ManagedBean 来表示一个JSF 模型——它与一个或多个特定的JSF 视图相关联。对于非 JSF 特定的业务逻辑和/或数据模型,您可以完美地使用 @EJBs。您可以在 JSF 模型中注入 @EJBs 并将其委托给操作方法,也许还有 getter/setter,但您不应该反过来,即不要在 @EJB 中定义 JSF 模型,这会导致紧密耦合并且会使@EJBs 在 JSF 上下文之外无法使用。就目前而言,您的设计听起来不错,只要您注意不要从 @EJB 类中的 javax.faces 包中导入任何内容。

【讨论】:

JSF 模型、验证器、请求处理——当然。仅在@ManagedBean 中执行此操作而在@EJB 中执行所有实际逻辑呢?它不需要意味着紧密耦合:@ManagedBean 被认为是表示层的一部分,但并非所有内容都必须通过它们。我仍然可以避免从 @EJB 到 JSF 的依赖关系并访问远程服务。只是试图区分两种(重叠?)bean类型。

以上是关于JSF2 - 由 EJB 或 ManagedBean 支持?的主要内容,如果未能解决你的问题,请参考以下文章

将 JSF2 托管 pojo bean 传递到 EJB 或将所需内容放入传输对象

什么时候需要或方便地使用 Spring 或 EJB3 或同时使用它们?

可以将@ManagedBean 作为@ManagedProperty 注入@WebServlet?

使用@EJB 时,每个托管bean 是不是都有自己的@EJB 实例?

如何让应用程序客户端从 EJB 获取事件和通知,由服务器推送?

EJB