我可以使用带有 CDI 的 EJB 无状态 Bean 来维护用户会话吗?
Posted
技术标签:
【中文标题】我可以使用带有 CDI 的 EJB 无状态 Bean 来维护用户会话吗?【英文标题】:Can I use EJB Stateless Bean with CDI to maintain user session? 【发布时间】:2011-09-13 19:14:17 【问题描述】:基于这篇帖子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 可以用于许多客户端。
使用具有所有 ejb 功能(事务、线程安全等)的托管 bean 的最佳方法是什么?我的意思是除了托管 bean + ejb 接口与 Java EE 5 中的实现 + ejb 注入之外的任何其他方式?
我使用 GlassFish 3.1 WebProfile
【问题讨论】:
感谢您的回答,那么我应该使用@Named @Stateful 还是 jsf 会话?哪个更好/更轻?当用户关闭浏览器和 ejb 会话时,jsf 会话结束? 或者也许将 ENtityManager 注入到 ManagedBean 中?安全吗? EJB 会话不一定会在用户关闭浏览器时结束,但 Web 用户以后将无法再次连接 EJB 会话。 EJB 代理通常保存在 http 会话、会话或视图范围内,当主 http 会话结束时,它们都会被销毁。 >或者也许将 EntityManager 注入到 ManagedBean 中? - 可能,但不如使用 EJB 方便,因为在这种情况下您需要自己处理启动、提交或回滚事务。如果托管 bean 被注入实体管理器,它也应该 - 不 - 是会话范围的。您需要将数据(会话范围)与数据库操作分开。实体管理器通常不是线程安全的。 【参考方案1】:补充duffymo的建议;使用有状态会话 bean 与使用 HTTP 会话相比,还有一些额外的注意事项。
HTTP 会话基本上具有类似地图的结构。它可直接用于会话中的所有线程(请求)。这使得操作多个项目成为相对不安全的操作。可以在会话本身上进行同步,但这是一个有风险的操作,可能会导致整个应用程序死锁。 HTTP 会话确实允许您声明事件侦听器,该事件侦听器会在对 http 会话进行任何类型的修改时触发。
Stateful session bean 当然有一个 bean 结构。它具有一种自动同步功能,因为只有线程可以同时在 bean 中处于活动状态。通过注解,您可以声明其他线程是否等待(如果等待,等待多长时间)或在面对并发访问时立即抛出异常。
在每个用户通常只有一个 http 会话的情况下,单个用户可以同时使用多个有状态会话 bean。有状态会话 bean 的一个特别优点是它们有一种机制可以在超时后钝化它们的状态,这可以释放服务器的内存(当然是以磁盘空间为代价的)。有状态会话 bean 不直接具有 http 会话所具有的那种事件侦听器。
我认为最初有状态会话 bean 的“会话”方面是维护与远程非 Web 客户端(Swing、另一个 AS 等)的会话。这很像为维护与远程 Web 客户端的会话而创建的 http 会话。由于非 Web 客户端可以为有状态会话 bean 请求并保留多个代理,因此 Web 类比实际上更类似于最近引入的 conversation scope
。
在远程 Web 客户端与服务器通信的情况下,服务器在内部与有状态会话 bean 通信,这些概念非常重叠。远程 Web 客户端只知道 http 会话(通过 JSESSIONID),而对有状态会话 bean 的会话一无所知。因此,如果 http 会话丢失,您通常将无法再次将远程客户端与特定的有状态会话 bean 连接。因此,在这种情况下,HTTP 会话始终处于领先地位,您不妨将购物车项目存储在单个 (http) 会话范围的 bean 中。
有一种特殊情况,有状态会话 bean 可以在内部通信中派上用场,那就是如果您需要 JPA 的 extended persistence context
。这可以用于例如实体上的锁定需要在请求之间持续(如果您的库存有限并且不想在用户实际结账时立即用“缺货”消息面对用户,这对于购物车来说可能很方便)。
【讨论】:
【参考方案2】:无状态 bean 无法维护购物车或会话;这就是“无国籍”的意思。
您需要有状态的 EJB 或在 Web 层中进行。这些是唯一保持会话的地方。
【讨论】:
以上是关于我可以使用带有 CDI 的 EJB 无状态 Bean 来维护用户会话吗?的主要内容,如果未能解决你的问题,请参考以下文章
我是不是还需要在 CDI bean 上使用 EJB @Clustered 来进行分布式应用程序
在较新版本的 JSF 中,@FacesValidator 和 @FacesConverter 中的 EJB 和 CDI 注入点无法通过 OmniFaces 工作