我正在尝试使用有状态会话 bean 编写 EJB 3.1。我应该很清楚什么是 EJB 以及有状态、无状态和单例之间的区别。
但是我的有状态豆有一个奇怪的行为。它表现得像一个单例!!我的意思是,从多个客户端/浏览器/机器调用下面的servlet(ShoppingCartServlet),返回相同的bean,并且每次都会增加相同的值。"count"值是从客户端共享的,因为 Bean 是单例。
请帮我理解!!
这里是代码。
Servlet 代码
@WebServlet(name="ShoppingCartServlet", urlPatterns="/shoppingCart")
public class ShoppingCartServlet extends HttpServlet {
private static final long serialVersionUID = 2789580260930727133L;
@EJB
private ShoppingCart shoppingCart;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int count = shoppingCart.increaseCount();
HttpSession session = request.getSession();
session.setAttribute("count", count);
String nextJSP = "/shoppingCart.jsp";
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(nextJSP);
dispatcher.forward(request, response);
}
}
EJB 代码
@Stateful
@LocalBean
public class ShoppingCart {
private int count;
public int increaseCount() {
count++;
return count;
}
}
Servlet 打包在 WAR 文件中,EJB 打包在 JAR 文件中。两者都部署在唯一的 EAR 文件中。
编辑:我试图像下面这样更改我的servlet代码,但现在每次调用都会创建一个新的有状态Bean。
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Context ctx = new InitialContext();
ShoppingCart shoppingCart = (ShoppingCart) ctx.lookup("java:global/jeeapp/jeeapp-business/ShoppingCart!org.madbit.jeeapp.shopping.ejb.ShoppingCart");
int count = shoppingCart.increaseCount();
HttpSession session = request.getSession();
session.setAttribute("count", count);
String nextJSP = "/shoppingCart.jsp";
RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(nextJSP);
dispatcher.forward(request, response);
}
有一个 servlet 实例同时用于多个请求。因此,它是注入的相同有状态 bean,由所有请求共享。
最好在 servlet 中使用局部变量而不是实例变量来实现线程安全。因此,您可以在方法中查找 bean,而不是在类级别注入。
编辑:
您可以将通过查找获得的 EJB 实例存储在 HttpSession
对象中,以供将来活动使用。因此,相同的实例将被重用,而不是每次都获取它,通过这种方式,会话状态将被保持。