如何使用有状态会话Bean使数据在页面之间保持持久性?

时间:2017-04-25 09:38:57

标签: java-ee tomee stateful-session-bean

我正在使用JEE购物车。我的Web应用程序由一个有状态会话bean和两个带有相应JSP页面的servlet组成。一个servlet允许将新项添加到购物车,另一个允许列出购物车的内容。

有状态会话bean应该跨页面保存购物车的状态,但购物车始终显示为空。你能帮助我找出我的代码有什么问题并解释为什么当前的实现还不够吗?

用于向购物车添加新商品的Servlet:

package my.servlet;

import my.entity.BookEntity;
import my.entity.ItemEntity;
import my.session.BookBean;
import my.session.CartBean;

import javax.ejb.EJB;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

@WebServlet("/item")
public class ItemServlet extends HttpServlet {

  @EJB
  private BookBean bookBean;

  @EJB
  private CartBean cartBean;

  @PersistenceContext(unitName = "book-pu")
  private EntityManager bookManager;

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
  {
    ServletContext ctx = getServletContext();
    long book = Long.parseLong(request.getParameter("book"), 10);
    RequestDispatcher dispatcher = ctx.getRequestDispatcher("/jsp/item.jsp");
    request.setAttribute("book", bookManager.find(BookEntity.class, book));
    request.setAttribute("item", null);
    dispatcher.forward(request, response);
  }

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
  {
    ServletContext ctx = getServletContext();
    int qty = Integer.parseInt(request.getParameter("qty"), 10);
    long book = Long.parseLong(request.getParameter("book"), 10);
    RequestDispatcher dispatcher = ctx.getRequestDispatcher("/jsp/item.jsp");
    ItemEntity item = new ItemEntity(bookManager.find(BookEntity.class, book), qty);
    request.setAttribute("book", bookManager.find(BookEntity.class, book));
    request.setAttribute("item", item);
    cartBean.addItem(item);
    dispatcher.forward(request, response);
  }
}

Servlet列出购物车的内容:

package my.servlet;

import my.session.CartBean;

import javax.ejb.EJB;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/cart")
public class CartServlet extends HttpServlet {

  @EJB
  private CartBean cartBean;

  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
  {
    ServletContext ctx = getServletContext();
    RequestDispatcher dispatcher = ctx.getRequestDispatcher("/jsp/cart.jsp");
    request.setAttribute("items", cartBean.getAllItems());
    dispatcher.forward(request, response);
  }
}

有状态会话Bean:

package my.session;

import java.util.ArrayList;
import java.util.Collection;

import javax.annotation.PostConstruct;
import javax.ejb.LocalBean;
import javax.ejb.Remove;
import javax.ejb.Stateful;
import javax.ejb.StatefulTimeout;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.concurrent.TimeUnit;
import my.entity.ItemEntity;

@LocalBean
@Stateful
@StatefulTimeout(unit = TimeUnit.MINUTES, value = 30)
public class CartBean implements CartItf {

  private Collection<ItemEntity> items;

  @PersistenceContext(unitName = "book-pu")
  private EntityManager itemManager;

  @PostConstruct
  public void initialize() {
    items = new ArrayList<ItemEntity>();
  }

  @Override
  public void addItem(ItemEntity item)
  {
    items.add(item);
  }

  @Override
  public Collection<ItemEntity> getAllItems()
  {
    return items;
  }

  @Remove
  @Override
  public void confirmOrder()
  {
    for (ItemEntity item : items) {
      itemManager.persist(item);
    }
  }
}

1 个答案:

答案 0 :(得分:1)

您需要确保每次(每个servlet)重用相同的有状态而不是新实例。您有多种选择:

  1. 添加@SessionScoped并使用@Inject而不是@EJB
  2. 以编程方式查找bean实例(new InitialContext())并将其放入HttpSession