【问题标题】:EJB 3.1 Stateful Bean behaves like a Singleton BeanEJB 3.1 有状态 Bean 的行为类似于单例 Bean
【发布时间】:2023-03-12 16:35:02
【问题描述】:

我正在尝试使用 Stateful Session 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);
}

【问题讨论】:

  • 也许您可以使用 JAX-RS 代替 servlet?

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


【解决方案1】:

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

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


编辑:

您可以将通过查找获得的 EJB 实例存储在 HttpSession 对象中以供将来使用。所以,同一个实例将被重用,而不是每次都获取它,通过这种方式,会话状态将被保持。

【讨论】:

  • 我会给出更强烈的建议:将有状态会话 bean 注入到无状态对象(servlet、无状态会话 bean 等)中绝不是一个好主意。
  • @bkail 感谢您的进一步澄清
  • 我已经更改了代码,在 doGet() servlet 方法中进行了查找,但现在每次调用都会创建一个新的有状态 Bean。 (有关详细信息,请参阅我的评论)
  • 也许更容易解释一下我会做什么,即在同一会话中的多个 jsp 页面上增加一个计数器(在有状态 bean 中)。
  • @Supertramp 请不要添加信息作为答案,而是更新原始帖子。另外,我已经更新了答案,请参阅编辑部分。
猜你喜欢
  • 2016-04-14
  • 2013-04-30
  • 2012-03-24
  • 2013-12-23
  • 2012-08-17
  • 2012-02-29
  • 1970-01-01
  • 2012-01-05
  • 1970-01-01
相关资源
最近更新 更多