购物车实现原理:一个购物车的实现

 

实现多个浏览器窗口可以共享购物车的技术。
1.几种实现的技术;
  --|cookie  
--|这种方案稍微简单些,开发起来简单方便,适合在单台服务器中使用时不错的方案。缺点是太占内存。
--|不太适合在多台服务器集群中使用。
  --|cookie+数据库
--|稍微复杂些
--|要求用户必须打开Cookie,或者通过参数(userid)URL+数据库。比较
--|不占内存,避免集群环境下的Session同步带来的性能损失,增加分布式的缓存(内存-硬盘)

  --------|可以同时实现两种

  --|EJB有状态bean

2.获取Session,怎样完成跨浏览器实现。重新打开浏览器是要通过SessionId获取先前的Session
  --|通过过滤器SiteSessionListener类来实现HttpSessionListener类来实现
  --|
  public class SiteSessionListener implements HttpSessionListener {

//使得Session的生命周期和用户的相同。
private static Map<String,HttpSession> session = new HashMap<String,HttpSession>();
public void sessionCreated(HttpSessionEvent sessionEvent) {
System.out.println(sessionEvent.getSession().getId());
session.put(sessionEvent.getSession().getId(), sessionEvent.getSession());
}

public void sessionDestroyed(HttpSessionEvent sessionEvent) {
session.remove(sessionEvent.getSession().getId());
}

public static HttpSession getSession(String sessionId){
return session.get(sessionId);
}

//删除SessionID的引用
public static void removeSession(String sessionID){
if(session.containsKey(sessionID)){
session.remove(sessionID);
}
}
 }
3.配置监听器
  --|在Web.xml文件中配置
      <!-- Session 的监听 -->
<listener>
 <listener-class>com.shop.web.filter.SiteSessionListener</listener-class>
</listener>

  --|在Action中
  @Controller("/product/cart")
  public class CartAction extends Action {
@Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
String sid = request.getParameter("sid");
HttpSession session = SiteSessionListener.getSession(sid);
if(session==null){
request.getSession().setAttribute("buycart", new Date());
}else{
request.setAttribute("message", session.getAttribute("buycart"));
}
return mapping.findForward("cart");
}
   }

  --|修改后的的execute方法:
   @Override
   public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
CartForm formbean = (CartForm)form;
BuyCart buycart = (BuyCart)request.getSession().getAttribute("buycart");
if(buycart==null){
//从Cookie中读取
String buycartid = WebUtil.getCookieByName(request, "buycartID");
if(buycartid!=null){
HttpSession session = SiteSessionListener.getSession(buycartid);
if(session!=null){
//从以前的购物车中取得
buycart = (BuyCart)request.getSession().getAttribute("buycart");
if(buycart!=null){
//清除原来的SessionId
SiteSessionListener.removeSession(buycartid);
request.getSession().setAttribute("buycart", buycart);
WebUtil.addCookie(response, "buycartID", 
    request.getSession().getId(), request.getSession().getMaxInactiveInterval());
}
}
}
}
//如果从以前的购物车中和Session中都取不到值。或者存在Session,而没有放商品到购物车中
if(buycart==null){
buycart = new BuyCart(); 
request.getSession().setAttribute("buycart", buycart);
WebUtil.addCookie(response, "buycartID", 
request.getSession().getId(), request.getSession().getMaxInactiveInterval());
}
if(formbean.getProductid()!=null && formbean.getProductid()>0){
ProductInfo product = productInfoService.find(ProductInfo.class, formbean.getProductid());
if(product!=null){
ProductStyle currentStyle = null; 
for(ProductStyle style :product.getStyles()){ //找到id对应的样式
if(style.getVisible() && style.getId().equals(formbean.getStyleid())){
currentStyle = style ;
break;
}
}
//清除产品样式中的所有样式,然后在加入当前的样式。这样只保证一个样式添加。
//产品是被维护端,所有不会更改数据库的记录,如果修改样式中的product属性,是会把修改的记录更新到数据库的
product.getStyles().clear(); 
if(currentStyle!=null)product.addProductStyle(currentStyle);
buycart.addItem(new BuyItem(product,1));//新添加产品到购物车中的数量是为1
}
}
request.setAttribute("buycart", buycart);
return mapping.findForward("cart");
}

4.把购物车想成是一个对象,设置里面的属性
   --|购物的清单ByIten 是List集合的类型
   --|创建购物项  里面的属性有 商品Product 
   --|只能放一个样式并且不能为空。数量amount 判断是否相等必须有hashCode和equeals方法(可以改写)
   --|添加方法 addItem(ByItem item)

   --|
      @Override
public int hashCode() {
//产品的HashCode就是product的Id
String buyItemcode= this.product.hashCode()+"-";
if(this.product.getStyles().size()>0){
//只得到一个样式,是第一个
buyItemcode+=product.getStyles().iterator().next().getId() ;
}
return buyItemcode.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final BuyItem other = (BuyItem) obj;
if (product == null) {
if (other.product != null)
return false;
} else if (!product.equals(other.product))
return false;
//只能放置但前的产品样式
if(product.getStyles().size()!=other.product.getStyles().size()){
return false;
}
if(product.getStyles().size()>0){
ProductStyle style = product.getStyles().iterator().next();
ProductStyle otherstyle =other.product.getStyles().iterator().next();
if(!style.equals(otherstyle))return false;
}
return true;
}

   --|购物车添加商品
     public class BuyCart {

private List<BuyItem> items = new ArrayList<BuyItem>();
/**
* 添加购物项
* @param item 商品
*/
public void addItem(BuyItem item){
//判断商品是否在购物车中了,在这个比较前要判断产品的Id和Style 的Id是否相同。
//在实体购物车中重新hashCode和equals方法
if(!items.contains(item)){
items.add(item);
}else{
for(BuyItem it :items){
if(it.equals(item)){
it.setAmount(it.getAmount()+1);
break;
}
}
   }
     }
}

6.在与前台页面交互的时候采用的小技巧:
        //productid-styleid
public void setBuyitemid(String buyitemid) {
this.buyitemid = buyitemid;
if(buyitemid!=null){
String[] values = this.buyitemid.split("-");
if(values.length==2){
this.productid = new Integer(values[0]);
this.styleid = new Integer(values[1]);
}
}
}

更新购物的数量:提交表单时用的name属性为
    amount_${item.product.id}_<c:forEach items="${item.product.styles}" var="style">${style.id}</c:forEach>
所以在Action中要生成这样的字段
public ActionForward updateAmount(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws Exception {
BuyCart buyCart = getBuyCart(request);
if(buyCart!=null){
for(BuyItem buyitem : buyCart.getItems()){
StringBuffer key = new StringBuffer("amount_");
key.append(buyitem.getProduct().getId()).append('_');
if(buyitem.getProduct().getStyles().size()>0){
key.append(buyitem.getProduct().getStyles().iterator().next().getId());
}
String amountStr = request.getParameter(key.toString());
if(amountStr!=null && !"".equals(amountStr)){
try{
int amount = Integer.parseInt(amountStr);
if(amount>0)buyitem.setAmount(amount);
}catch(Exception e){ }
}
}
}
return mapping.findForward("result");
}
Tags:  cookie实现购物车 购物车实现方法 如何实现购物车 购物车实现原理

延伸阅读

最新评论

发表评论