EJB 3.1 Stateful Bean的行为类似于Singleton Bean

时间:2012-12-16 16:48:25

标签: ejb-3.1 stateful stateful-session-bean

我正在尝试使用有状态会话bean对EJB 3.1进行编程。 我应该很清楚EJB是什么以及有状态,无状态和单身之间的区别。

但我的有状态bean有一种奇怪的行为。它表现得像一个单身人士! 我的意思是从几个客户端/浏览器/机器调用下面的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代码,如下所示,但现在每次调用都会创建一个新的Stateful 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);
}

1 个答案:

答案 0 :(得分:2)

单个servlet实例同时重用多个请求。因此,它是注入的同一个有状态bean,由所有请求共享。

使用局部变量是一种很好的做法,而不是servlet中线程安全的实例变量。因此,您可以在方法中查找bean,而不是在类级别注入。


修改:

您可以将通过查找获得的EJB实例存储在HttpSession对象中以供将来活动使用。因此,相同的实例将被重复使用而不是每次都获得它。通过这种方式,将维持会话状态。