使用有状态会话Bean来跟踪用户会话

16

这是我在这里的第一个问题,希望我做得没错。

我需要处理一个Java EE项目,因此,在开始之前,我正在尝试做一些简单的事情,并查看是否可以做到。

我卡在了状态会话Bean上。

问题在于: 如何使用SFSB跟踪用户的会话? 我看到的所有示例最终都将SFSB放入HttpSession属性中。 但我不明白为什么! 我的意思是,如果bean是STATEFUL,为什么我必须使用HttpSession来保留它?

难道EJB容器的任务不是向客户端返回正确的SFSB吗?

我已经尝试过一个简单的计数器bean。 没有使用session,两个不同的浏览器有相同的计数器bean(点击“增加”会同时改变它们的值)。 使用session,我有两个不同的值,每个浏览器都有自己的值(在Firefox上单击“增加”只为Firefox的bean添加1)。

但是我的老师告诉我,SFSB与客户端保持“对话状态”,那么为什么不能在不使用HttpSession的情况下正常工作呢?

如果我理解正确,使用SFSB和HttpSession是否与使用SLSB相同?

我希望我的问题清晰明了,而且我的英语不是太差!

编辑: 我正在处理一个登录系统。 一切都很好,在完成登录后,它会带我到显示用户数据的个人资料页面。 但是重新加载页面会使我的数据消失! 我尝试在登录时添加HttpSession,但这样做会使数据在注销后仍然保留!

2个回答

31
在Web环境中,状态会话Bean(SFSB)必须与HTTP会话结合使用,因为它是一个纯业务Bean,本身对Web层一无所知。传统上,EJB甚至强制性地生存在自己的模块(EJB模块)中,如果需要,甚至不能访问Web工件。这是分层系统的一个方面。有关此信息,请参见将EJB打包在JavaEE 6 WAR vs EAR
最初的Stateful Session Beans客户端包括Swing桌面应用程序,通过二进制协议与远程EJB服务器通信。Swing应用程序将通过代理/存根对象获取到远程Stateful Session Bean的连接。嵌入在此代理中的是某种ID,服务器可以将其与特定的SFSB相关联。通过持有此代理对象,Swing客户端可以进行重复调用,并且这些调用将转到同一个bean实例。这将创建客户端和服务器之间的会话。
在Web应用程序的情况下,当浏览器向Java EE Web应用程序发出初始请求时,它会获得一个JSESSIONID,服务器可以将其与特定的HTTPSession实例相关联。通过持有此JSESSIONID,浏览器可以在每个后续请求中提供它,并且这将在服务器端激活相同的HTTP会话。
因此,这些概念非常相似,但它们不会自动映射到彼此。

浏览器只获取JSESSIONID,并不知道任何SFSB ID。与Swing应用程序不同,浏览器与网页通信,而不是直接与Java bean通信。

为了将客户端的请求映射到特定的有状态会话bean,EJB容器只关心通过SFSB代理提供的ID。它看不到调用是否来自Web模块中的代码,也不能/不应该访问任何HTTP上下文。

作为访问SFSB的客户端代码,Web层必须“保持”特定的代理引用。在Web层保留某些内容通常意味着将其存储在HTTP会话中。

然而,有一种名为CDI的桥接技术可以进行自动连接。如果您使用CDI的@SessionScoped注释对SFSB进行注释,并通过CDI(例如使用@Inject)获取对SFSB的引用,则无需手动将SFSB放入http会话中。但是,在幕后,CDI将执行完全相同的操作。


很好的回答,Arjan。不过,我相信你在最后一段回答中想说的是@SessionScoped。 - Zach-M

3

如果你正在寻找 HttpSession 的等效解决方案,你需要使用 @SessionScoped 而不是 @RequestScoped 来定义 bean。

类似这样:

@SessionScoped
public class SessionInfo implements Serializable{
   private String name;
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
}

请查看以下内容(详细说明): http://www.oracle.com/technetwork/articles/java/cdi-javaee-bien-225152.html

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