我可以使用EJB Stateless Bean和CDI来维护用户会话吗?

3

根据这篇文章http://www.adam-bien.com/roller/abien/entry/ejb_3_1_killed_the,我在我的应用程序中使用@Named @Stateless bean与数据库进行通信(在此处注入EntityManager)并在jsf页面上显示信息。自从Java EE 5以来,这是一个很好的便利,但我有一个问题。

使用这样的bean来维护用户会话(购物车等)是否安全?我读过一本关于ejb 3.0的书籍,知道同一个无状态bean可以与许多客户端一起使用。

除了Java EE 5中的托管bean + ejb接口实现和ejb注入之外,还有什么其他方法可以使用所有ejb功能(事务,线程安全性等)的最佳方法?

我使用GlassFish 3.1 WebProfile


谢谢您的回答,那我应该使用@Named @Stateful还是jsf session呢?哪个更好/轻量级?当用户关闭浏览器时,jsf会话会结束,而ejb会话呢? - m1m
或者将EntityManager注入到ManagedBean中?这样安全吗? - m1m
1
一个EJB会话并不一定在用户关闭浏览器时结束,但是后续没有办法让Web用户再次连接到EJB会话。EJB代理通常保存在http会话、对话或视图范围中,当主要的http会话结束时,它们都会被销毁。 - Arjan Tijms
或许可以将一个EntityManager注入到一个ManagedBean中?- 可能是可以的,但与使用EJB相比较不方便,因为在这种情况下你必须自己负责启动、提交或回滚事务。如果通过注入实体管理器来使用托管Bean,则该托管Bean也不应该被设为会话范围。你需要将数据(会话范围)和数据库操作分开。通常情况下,实体管理器不是线程安全的。 - Arjan Tijms
2个回答

10

除了duffymo的建议外,使用有状态会话Bean与使用HTTP会话还有一些额外的考虑因素。

HTTP会话基本上具有类似于映射的结构。它直接对所有作为会话一部分的线程(请求)可用。这使得操作多个项成为相对不安全的行为。可以在会话本身上进行同步,但这是一种风险操作,可能会死锁整个应用程序。HTTP会话确实允许您声明事件侦听器,在任何修改http会话的情况下触发。

有状态会话bean当然具有bean结构。它具有一种自动同步功能,因为同一时间只有一个线程可以在bean中处于活动状态。通过注释,您可以声明其他线程等待(如果是这样的话,等待多长时间),或者在面对并发访问时立即抛出异常。

通常每个用户只有一个HTTP会话,但单个用户可以同时使用多个有状态会话bean。有状态会话bean的一个特别优点是,它们具有一种机制,在某些超时后使其状态失效,这可以释放服务器的内存(当然会占用磁盘空间)。有状态会话bean没有像HTTP会话一样的事件监听器。

我认为,最初有状态会话bean的“会话”方面是为了与远程非Web客户端(Swing,另一个AS等)保持会话。这很像HTTP会话被创建来与远程Web客户端保持会话。由于非Web客户端可以请求并保存多个有状态会话bean的代理,因此Web类比实际上更类似于最近引入的conversation scope

在远程Web客户端与服务器通信的情况下,服务器内部与有状态会话bean交谈时,概念重叠得非常大。远程Web客户端仅知道HTTP会话(通过JSESSIONID),并且对有状态会话bean的会话一无所知。因此,如果HTTP会话丢失,您通常将无法再将远程客户端连接到特定的有状态会话bean。在这种情况下,HTTP会话始终处于领先地位,您可能会将购物车项存储在单个(http)会话范围的bean中。

有一种特殊情况下,有状态会话Bean在内部通信中非常方便,那就是当你需要JPA的扩展持久性上下文时。如果例如需要实体的锁在请求之间持续存在(这对于购物车来说可能很方便,如果你有限定库存并且不想在用户结账时立即显示“缺货”消息)。


6

无状态 Bean 不能维护购物车或会话;这就是 “无状态” 的含义。

您需要使用有状态的 EJB 或在 Web 层中执行此操作。这些是唯一维护会话的地方。


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