@SessionScoped (CDI) 和 @Stateful (Java EE) 之间的区别

Cod*_*bal 2 annotations stateful session-scope cdi jakarta-ee

我了解到 CDI Bean 可以用于不同的基于 Web 应用程序的范围(仅限于此,对吧?)。例如:@RequestScoped、@SessionScoped等。@SessionScoped 将数据保存在整个浏览器会话上的托管 bean 中。这在逻辑上听起来很安静,因为注释名称描述了它的作用。然而,现在我更仔细地了解了 EJB 会话 Bean。到目前为止我知道,这样的状态可能具有以下三种状态之一:@Stateless、@Stateful 和@Singleton。对我来说,看起来它们和 CDI bean 的注释之间有直接的可比性:@RequestScoped --> @Stateless、@SessionScoped --> @Stateful、@ApplicationScoped --> @Singleton。但由于我正在研究一些示例,我发现了一个同时包含 @Stateful 和 @SessionScoped 注释的 bean。我寻找解释 - 但我没有找到任何可以理解的答案。那么,到底有什么区别呢?为什么我必须使用这两个注释?谢谢。

Sil*_*rus 5

CDI Bean 可以在不同的基于 Web 应用程序的范围中使用(仅限于此,对吧?)。

错误的。CDI bean 可以用在您想要的任何地方 - 数据库连接/通信、业务逻辑、基于事件的编程,甚至在 Java SE 中也是如此(Weld,CDI 的参考实现,现在也提供了这一点)。然而,特别@SessionScoped是 bean 在 HTTP 会话中比在其他任何地方都更有意义。但您仍然可以将会话想象(并使用)为具有标记开始和结束的给定时间段。在这些边界内,会话是存在的 - 不一定是 HTTP 会话,但它是最明显的会话。

它们与 CDI bean 的注释之间有直接的可比性:@RequestScoped --> @Stateless、@SessionScoped --> @Stateful、@ApplicationScoped --> @Singleton。

又错了。EJB 仅链接到 Web 通信,而 CDI 则不然。另外,根据您选择的注释,您还可以选择一个负责该 bean 的容器 (CDI/EJB)。CDI 集成了所有 EJB bean(创建代理并使其“看似”是一个 CDI bean - 允许您在 EJB bean 中使用 CDI 内容)。

例如,现在@Stateless在 CDi/Weld 中内部表示为@Dependent范围,而不是@RequestScoped因为@StatelessEJB 中的 bean 被重用,并且您不能依赖它们的状态。在 CDI中@RequestScoped,您激活请求上下文(让我们坚持使用 HTTP,因此通过发送一些内容来激活它),这会触发所有 bean 的创建@RequestScoped。请求之后,所有这些 bean 都被销毁,不再使用。因此,您可以完全依赖您放入其中的内容,并且您还可以确保它不会在请求后继续存在。

另一个故事是@ApplicationScoped对抗@Singleton。它们确实非常相似,最重要的细节可能是 CDI 创建自己的 Bean 代理。但这对于这个问题来说太详细了,我想你现在可以认为它们具有可比性。

@SessionScoped (CDI) 和 @Stateful (Java EE) 之间的区别

现在终于回到原来的问题了。我认为要总体上掌握这些差异,您需要了解 CDI 在上下文中运行的事实。它总是激活上下文(在本例中为会话上下文),此时@SessionScoped会出现一组 bean,您可以与它们进行通信,它们具有值和状态等。上下文相互交叉,因此请求上下文可能同时存在,并且应用程序上下文确实存在。因此,我们可以说它@SessionScoped与会话相关并由容器控制,同时@Stateful为您提供了用户管理的会话,其生命周期由客户端管理,并且在此基础上还添加了许多其他功能。

有时您可以在一个 bean 上看到两个注释的原因是人们将它们组合起来以获得两个世界的最佳效果 - 容器管理的生命周期和添加的功能。但请注意,虽然@Stateful目前使用不多(选择加入通常更有意义@Stateless),@SessionScope但它更加通用,并且适合几乎任何基于会话的场景。

希望它至少能提供一些线索,恐怕这是一个非常复杂的话题。