Jakarta ee 将有状态会话bean与servlet一起使用

Jakarta ee 将有状态会话bean与servlet一起使用,jakarta-ee,ejb,ejb-3.0,Jakarta Ee,Ejb,Ejb 3.0,我正在用Glassfish服务器(一个简单的购物车)尝试我的第一个EJB。我打算在每个Http会话中使用CartBean。如果我的购物车Bean正在跟踪- public interface CartLocal { public void addItem(String item); public void removeItem(String item); } @Stateful public class CartBean implements CartLocal { List<Str

我正在用Glassfish服务器(一个简单的购物车)尝试我的第一个EJB。我打算在每个Http会话中使用CartBean。如果我的购物车Bean正在跟踪-

public interface CartLocal {
 public void addItem(String item);
 public void removeItem(String item);
}

@Stateful
public class CartBean implements CartLocal {
 List<String> item = new java.util.ArrayList<String>();
 public void addItem(String item) {
  ....
 }
 public void removeItem(String item) {
  ....
 }
}

http servlet由该servlet的所有客户机共享,因此向其注入有状态会话bean是不正确的,并将导致不良后果。会话bean用于每个客户端,它们通常存储在http会话中,以便该会话的所有请求都可以访问会话bean。您必须在
doGet
方法中使用jndi查找,并将该引用存储在http会话中。一旦存储,您将需要从http会话中检索并使用该会话

更多信息

你弄错了。有状态会话bean类表示如何对有状态数据建模,该数据可以是细粒度相关类的图形。你从容器里要了一粒扁豆 这些服务就是我们使用有状态会话bean的目的。然而,容器不知道它所移交的任何对象属于哪个客户机。于是http会话就出现了。这一部分并没有被强调的那么多,因此你们感到困惑。Http会话是一个完美的存储场所,来自同一web客户端的所有请求都可以访问Http会话中存储的所有属性。因此,您可以从容器中请求它,并将它保存在一个位置(http会话),在该位置,同一会话的所有请求都可以再次引用它。现在想象一下非web客户端的情况。这里没有http会话或类似的机制。您必须创建自己的存储机制,以使用各自的有状态bean标识不同的客户端。一种可能的方法可能是将有状态bean引用存储在某个位置(例如,在一个映射中,key作为clientId,value作为bean引用),下次客户端想要访问bean时,它会传递clientId并从映射中获取它

就http会话优先于有状态bean而言,理解http会话不是线程安全的是很重要的。所以,如果您有一个ajax应用程序同时访问会话中的对象,您必须提供自己的同步机制,这将 不可扩展,会严重影响性能。对于有状态会话bean,容器管理同步


是关于使用http会话存储状态的有趣讨论。讨论内容是Brian Goetz的一篇内容丰富的文章“所有有状态的Java Web应用程序都坏了吗?”。不幸的是,我无法在IBM网站上找到原始文章,但讨论线程提供了足够的材料供思考。

您当然可以使用有状态bean,但您不能注入它,因为默认情况下,单个servlet实例可以被共享以同时服务多个请求,这意味着您的代码不是线程安全的。但是,例如,您可以在
doGet
方法中执行
JNDI
查找

CartBean bean = (CartBean) new InitialContext().lookup(jndiName);

查看一些查找教程。

我完全理解购物车应该使用HttpSession而不是SFSB进行管理。但为什么我到处寻找,只提供购物车作为SFSB的例子。我想知道SFSB真正有用的实际情况。我认为将SFSB保持在Http会话中比将购物车本身保持在会话中更糟糕
CartBean bean = (CartBean) new InitialContext().lookup(jndiName);