taotao购物车

功能分析:

1、在用户不登陆的情况下也可以使用购物车,那么就需要把购物车信息放入cookie中。

2、可以把商品信息,存放到pojo中,然后序列化成json存入cookie中。

3、取商品信息可以从cookie中把json数据取出来,然后转换成java对象即可。

4、此功能只需要操作cookie不需要数据库的支持,所以只需要在taotao-portal中实现即可。

5、购物车分有四种动作

a) 添加商品

b) 修改商品数量

c) 删除购物车中的商品

d) 展示购物车商品列表

service层代码:

package com.taotao.portal.service.impl;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.taotao.common.pojo.TaotaoResult;
import com.taotao.common.utils.CookieUtils;
import com.taotao.common.utils.HttpClientUtil;
import com.taotao.common.utils.JsonUtils;
import com.taotao.pojo.TbItem;
import com.taotao.portal.pojo.CartItem;
import com.taotao.portal.service.CartService;
/**
 * 购物车service
 * @author Administrator
 */
@Service
public class CartServiceImpl implements CartService {

    //rest服务基础url
    @Value("${REST_BASE_URL}")
    private String REST_BASE_URL;
    //获取商品信息的url
    @Value("${ITEM_INFO_URL}")
    private String ITEM_INFO_URL;
    
    /**
     * 添加购物车商品
     * 
        1、接收controller传递过来的商品id,根据商品id查询商品信息。
        2、从cookie中取出购物车信息,转换成商品pojo列表。
        3、把商品信息添加到商品列表中。
        参数:
        1、商品id
        2、Request
        3、response
        返回值:
        TaoTaoResult
        
        同时此方法还可以作为 
        点击购物车商品的“+”、“-”号时增加或减少商品数量 的方法,
        点 加号时,传参数 num = 1
        点 减号时,传参数 num = -1
     */
    @Override
    public TaotaoResult addCartItem(long itemId, int num,
            HttpServletRequest request,HttpServletResponse response) {
        //当前id对应的购物车商品
        CartItem cartItem = null;
        //从cookie中获取购物车列表
        List<CartItem> cartList = getCartItemList(request);
        //先判断原购物车列表中是否有当前商品
        for (CartItem item : cartList) {
            //如果存在
            if (item.getId()==itemId) {
                //增加商品数量
                item.setNum(item.getNum()+num);
                cartItem = item;
                break;
            }
        }
        //如果原来没有此商品,则新建
        if (cartItem==null) {
            cartItem = new CartItem();
            //调用rest服务获取商品信息
            String doGetResult = HttpClientUtil.doGet(REST_BASE_URL+ITEM_INFO_URL+itemId);
            TaotaoResult taoTaoResult = TaotaoResult.formatToPojo(doGetResult, TbItem.class);
            if (taoTaoResult.getStatus()==200) {
                //封装成购物车商品对象
                TbItem item = (TbItem) taoTaoResult.getData();
                cartItem.setId(itemId);
                cartItem.setImage(item.getImage()==null?"":item.getImage().split(",")[0]);
                cartItem.setPrice(item.getPrice());
                cartItem.setTitle(item.getTitle());
                cartItem.setSellPoint(item.getSellPoint());
                cartItem.setNum(num);
                //将商品加入到购物车列表中
                cartList.add(cartItem);
            }
        }
        //将购物车列表写回cookie
        String listJson = JsonUtils.objectToJson(cartList);
        //最后一个参数 true,对数据进行编码,这样在 cookie中就看不到中文原始数据了
        CookieUtils.setCookie(request, response, "TT_CART", listJson,true);
        return TaotaoResult.ok();
    }
    
    /**
     * 从cookie中取商品列表
     * @param request
     * @return
     */
    private List<CartItem> getCartItemList(HttpServletRequest request) {
        //从cookie中取商品列表
        String cartJson = CookieUtils.getCookieValue(request, "TT_CART",true);
        if (cartJson==null) {
            return new ArrayList<CartItem>();
        }
        //把json转换为商品列表
        try {
            List<CartItem>  list = JsonUtils.jsonToList(cartJson, CartItem.class);
            return list;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new ArrayList<CartItem>();
    }

    /**
     * 获取 购物车商品列表供前台展示
     */
    @Override
    public List<CartItem> getCartItemList(HttpServletRequest request, HttpServletResponse response) {
        List<CartItem> result = getCartItemList(request);
        return result;
    }
    
    /**
     * 直接输入数量,更新购物车中商品的数量(在购物车列表展示页面中使用)
     */
    @Override
    public TaotaoResult updateCartItmeNum(long itemId, int num,
            HttpServletRequest request, HttpServletResponse response){
        //当前id对应的购物车商品
        CartItem cartItem = null;
        //从cookie中获取购物车列表
        List<CartItem> cartList = getCartItemList(request);
        //先判断原购物车列表中是否有当前商品
        for (CartItem item : cartList) {
            //如果存在
            if (item.getId()==itemId) {
                //修改商品数量
                item.setNum(num);
                cartItem = item;
                break;
            }
        }
        //将购物车列表写回cookie
        String listJson = JsonUtils.objectToJson(cartList);
        //最后一个参数 true,对数据进行编码,这样在 cookie中就看不到中文原始数据了
        CookieUtils.setCookie(request, response, "TT_CART", listJson,true);
        return TaotaoResult.ok();
    }
    
    /**
     * 删除购物车中商品
     * @param itemId
     * @param request
     * @param response
     * @return
     */
    @Override
    public TaotaoResult delCartItem(long itemId,
            HttpServletRequest request, HttpServletResponse response){
        //当前id对应的购物车商品
        CartItem cartItem = null;
        //从cookie中获取购物车列表
        List<CartItem> cartList = getCartItemList(request);
        Iterator<CartItem> iterator = cartList.iterator();
        //遍历
        while (iterator.hasNext()) {
            CartItem item = iterator.next();
            //找到对应的商品
            if (item.getId()==itemId) {
                //执行删除动作
                iterator.remove();
                break;
            }
        }
        
        //将购物车列表写回cookie
        String listJson = JsonUtils.objectToJson(cartList);
        //最后一个参数 true,对数据进行编码,这样在 cookie中就看不到中文原始数据了
        CookieUtils.setCookie(request, response, "TT_CART", listJson,true);
        return TaotaoResult.ok();
    }

}

Controller 层代码:

package com.taotao.portal.controller;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.taotao.portal.pojo.CartItem;
import com.taotao.portal.service.CartService;

/**
 * 购物车的Controller
 * @author Administrator
 */
@Controller
@RequestMapping("/cart")
public class CartController {
    
    @Autowired
    private CartService cartService;
    /**
     * 添加商品到购物车
     * @param itemId
     * @param num
     * @param request
     * @param response
     * @return
     * 
     * 同时此方法还可以作为 
        点击购物车商品的“+”、“-”号时增加或减少商品数量 的方法,
        点 加号时,传参数 num = 1
        点 减号时,传参数 num = -1
     */
    @RequestMapping("/add/{itemId}")
    public String addCartItem(@PathVariable Long itemId,
            @RequestParam(defaultValue="1")Integer num,
            HttpServletRequest request,HttpServletResponse response) {
        cartService.addCartItem(itemId, num, request, response);
//        return "cartSuccess"; //这样会打开新的页面,所以不用
        //为了 避免每次添加完商品都打开新的页面,所以这里这样重定向
        return "redirect:/cart/success.html";
//        return "forward:/cart/success.html"; //这种写法也可以(请求转发)
    }
    
    //接收重定向的请求返回jsp页面
    @RequestMapping("/success")
    public String showSuccess(){
        return "cartSuccess";
    }
    
    /**
     * 查询购物车中的商品列表返回前台展示
     * @param request
     * @param response
     * @param model
     * @return
     */
    @RequestMapping("/cart")
    public String showCart(HttpServletRequest request,HttpServletResponse response,Model model){
        List<CartItem> cartItemList = cartService.getCartItemList(request, response);
        model.addAttribute("cartList", cartItemList);
        return "cart";
    }
    
    /**
     * 手动填写直接修改商品数量
     * @param itemId
     * @param num
     * @param request
     * @param response
     * @return
     */
    @RequestMapping("/update/{itemId}")
    public String updateCartItemNum(@PathVariable Long itemId,
            @RequestParam(defaultValue="0")Integer num,
            HttpServletRequest request,HttpServletResponse response) {
        cartService.updateCartItmeNum(itemId, num, request, response);
        return "redirect:/cart/cart.html";
    }
    
    /**
     * 删除购物车中的指定商品
     * @param itemId
     * @param request
     * @param response
     * @return
     */
    @RequestMapping("/delete/{itemId}")
    public String delCartItem(@PathVariable Long itemId,
            HttpServletRequest request,HttpServletResponse response){
        cartService.delCartItem(itemId, request, response);
        return "redirect:/cart/cart.html";
    }
}

添加完购物车后的成功跳转页:

cartSuccess.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page trimDirectiveWhitespaces="true" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>${item.title } - 淘淘</title>
    <script>var jdpts = new Object(); jdpts._st = new Date().getTime();</script>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <link rel="stylesheet" type="text/css" href="/css/taotao.css" media="all" />
    <link rel="stylesheet" type="text/css" href="/css/pshow.css" media="all" />
    <script type="text/javascript">
        window.pageConfig = {
            compatible: true,
               product: {
                skuid: 1221882,
                name: 'u957fu8679uff08u0043u0048u0041u004eu0047u0048u004fu004eu0047uff09u004cu0045u0044u0034u0032u0035u0033u0038u0045u0053u0020u0034u0032u82f1u5bf8u0020u7a84u8fb9u84ddu5149u004cu0045u0044u6db2u6676u7535u89c6uff08u9ed1u8272uff09',
                skuidkey:'E804B1D153D29E36088A33A134D85EEA',
                href: 'http://item.jd.com/1221882.html',
                src: 'jfs/t304/157/750353441/93159/e4ee9876/54227256N20d4f5ec.jpg',
                cat: [737,794,798],
                brand: 20710,
                nBrand: 20710,
                tips: false,
                type: 1,
                venderId:0,
                shopId:'0',
                TJ:'0',
                specialAttrs:["HYKHSP-0","isHaveYB","isSelfService-0","isWeChatStock-0","isCanUseJQ","isOverseaPurchase-0","YuShou","is7ToReturn-1","isCanVAT"],
                videoPath:'',
                HM:'0'
            }
        };
    </script>
</head>
<body version="140120">
<script type="text/javascript">try{(function(flag){ if(!flag){return;} if(window.location.hash == '#m'){var exp = new Date();exp.setTime(exp.getTime() + 30 * 24 * 60 * 60 * 1000);document.cookie = "pcm=1;expires=" + exp.toGMTString() + ";path=/;domain=jd.com";return;}else{var cook=document.cookie.match(new RegExp("(^| )pcm=([^;]*)(;|$)"));var flag=false;if(cook&&cook.length>2&&unescape(cook[2])=="1"){flag=true;}} var userAgent = navigator.userAgent; if(userAgent){ userAgent = userAgent.toUpperCase();if(userAgent.indexOf("PAD")>-1){return;} var mobilePhoneList = ["IOS","IPHONE","ANDROID","WINDOWS PHONE"];for(var i=0,len=mobilePhoneList.length;i<len;i++){ if(userAgent.indexOf(mobilePhoneList[i])>-1){var url="http://m.jd.com/product/"+pageConfig.product.skuid+".html";if(flag){pageConfig.product.showtouchurl=true;}else{window.location.href = url;}break;}}}})((function(){var json={"6881":3,"1195":3,"10011":3,"6980":3,"12360":3};if(json[pageConfig.product.cat[0]+""]==1||json[pageConfig.product.cat[1]+""]==2||json[pageConfig.product.cat[2]+""]==3){return false;}else{return true;}})());}catch(e){}</script>
<!-- header start -->
<jsp:include page="commons/header.jsp" />
    商品已经成功加入购物车 <a href ="/cart/cart.html">去购物车结算</a>
    <jsp:include page="commons/footer.jsp" />
</body>
</html>

购物车列表页的jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page trimDirectiveWhitespaces="true" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head>
   <meta http-equiv="pragma" content="no-cache">
   <meta http-equiv="cache-control" content="no-cache">
   <meta http-equiv="expires" content="0"> 
   <meta name="format-detection" content="telephone=no">  
   <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> 
   <meta name="format-detection" content="telephone=no">
   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   <link rel="stylesheet" href="/css/base.css">
   <link href="/css/purchase.2012.css?v=201410141639" rel="stylesheet" type="text/css">
   <title>我的购物车 - 淘淘商城</title>
   <script>
       var pageConfig  = {};
   </script>
<body> 
<!--shortcut start-->
<jsp:include page="commons/shortcut.jsp" />
<!--shortcut end-->
<div class="w w1 header clearfix">
    <div id="logo"><a href="/"><img clstag="clickcart|keycount|xincart|logo" src="/images/taotao-logo.gif" title="返回淘淘商城首页" alt="返回淘淘商城首页"></a></div>
    <div class="language"><a href="javascript:void(0);" onclick="toEnCart()"></a></div>
    <div class="progress clearfix">
        <ul class="progress-1">
            <li class="step-1"><b></b>1.我的购物车</li>
            <li class="step-2"><b></b>2.填写核对订单信息</li>
            <li class="step-3">3.成功提交订单</li>
        </ul>
    </div>
</div>
<div class="w cart">
    <div class="cart-hd group">
        <h2>我的购物车</h2>
    </div>
    <div id="show">
    
<div class="cart-frame">
    <div class="tl"></div>
    <div class="tr"></div>
</div>
<div class="cart-inner">
    <div class="cart-thead clearfix">
        <div class="column t-checkbox form"><input data-cart="toggle-cb" name="toggle-checkboxes" id="toggle-checkboxes_up" type="checkbox" checked="" value=""><label for="toggle-checkboxes_up">全选</label></div>
        <div class="column t-goods">商品</div>
        <div class="column t-price">淘淘价</div>
        <div class="column t-promotion">优惠</div>
        <div class="column t-inventory">库存</div>
        <div class="column t-quantity">数量</div>
        <div class="column t-action">操作</div>
    </div>
    <div id="product-list" class="cart-tbody">
        <!-- ************************商品开始********************* -->
        <c:set var="totalPrice" value="0"></c:set>
        <c:forEach items="${cartList}" var="cart">
            <c:set var="totalPrice"  value="${ totalPrice + (cart.price * cart.num)}"/>
            <div id="product_11345721" data-bind="rowid:1" class="item item_selected ">
                <div class="item_form clearfix">
                    <div class="cell p-checkbox"><input data-bind="cbid:1" class="checkbox" type="checkbox" name="checkItem" checked="" value="11345721-1"></div>
                    <div class="cell p-goods">
                        <div class="p-img">
                            <a href="/item/${cart.id }.html" target="_blank">
                                <img clstag="clickcart|keycount|xincart|p-imglistcart" src="${cart.image}" alt="${cart.title}" width="52" height="52">
                            </a>
                        </div>    
                        <div class="p-name">
                            <a href="/item/${cart.id }.html" clstag="clickcart|keycount|xincart|productnamelink" target="_blank">${cart.title}</a>
                            <span class="promise411 promise411_11345721" id="promise411_11345721"></span>
                        </div>    
                    </div>
                    <div class="cell p-price"><span class="price">¥<fmt:formatNumber groupingUsed="false" value="${cart.price / 100}" maxFractionDigits="2" minFractionDigits="2"/> </span></div>
                    <div class="cell p-promotion">
                    </div>
                    <div class="cell p-inventory stock-11345721">有货</div>
                    <div class="cell p-quantity" for-stock="for-stock-11345721">
                        <div class="quantity-form" data-bind="">
                            <a href="javascript:void(0);" class="decrement" clstag="clickcart|keycount|xincart|diminish1" id="decrement">-</a>
                            <input type="text" class="quantity-text" itemPrice="${cart.price}" itemId="${cart.id}" value="${cart.num }" id="changeQuantity-11345721-1-1-0">
                            <a href="javascript:void(0);" class="increment" clstag="clickcart|keycount|xincart|add1" id="increment">+</a>
                        </div>
                    </div>
                    <div class="cell p-remove"><a id="remove-11345721-1" data-more="removed-87.20-1" clstag="clickcart|keycount|xincart|btndel318558" class="cart-remove" href="/cart/delete/${cart.id}.html">删除</a>
                    </div>
                </div>
            </div> 
        </c:forEach>
        
    </div><!-- product-list结束 -->
          <div class="cart-toolbar clearfix">
            <div class="total fr">
                <p><span class="totalSkuPrice">¥<fmt:formatNumber value="${totalPrice / 100}" maxFractionDigits="2" minFractionDigits="2" groupingUsed="true"/></span>总计:</p>
                <p><span id="totalRePrice">- ¥0.00</span>优惠:</p>
            </div>
            <div class="amout fr"><span id="selectedCount">1</span> 件商品</div>
        </div>
        <div class="ui-ceilinglamp-1" style=" 988px; height: 49px;"><div class="cart-dibu ui-ceilinglamp-current" style=" 988px; height: 49px;">
          <div class="control fdibu fdibucurrent">
              <span class="column t-checkbox form">
                  <input data-cart="toggle-cb" name="toggle-checkboxes" id="toggle-checkboxes_down" type="checkbox" checked="" value="" class="jdcheckbox">
                  <label for="toggle-checkboxes_down">
                          全选
                  </label>
              </span>
              <span class="delete">
                  <b>
                  </b>
                  <a href="javascript:void(0);" clstag="clickcart|keycount|xincart|clearcartlink" id="remove-batch">
                          删除选中的商品
                  </a>
              </span>
              <span class="shopping">
                  <b>
                  </b>
                  <a href="/" target="_blank" clstag="clickcart|keycount|xincart|coudanlink" id="continue">继续购物</a>
              </span>
          </div>
          <div class="cart-total-2014">
              <div class="cart-button">
                  <span class="check-comm-btns" id="checkout-jd">
                      <a class="checkout" href="/order/order-cart.html" clstag="clickcart|keycount|xincart|gotoOrderInfo" id="toSettlement">去结算<b></b></a>
                  </span>
                  <span class="combine-btns" style="display:none">
                        <span class="fore1" style="display: none;">
                          <a href="" class="combine-btn">不支持合并付款</a>
                      </span>
                      <span class="fore2 hide" style="display: inline;">
                          <a href="javascript:goToOverseaOrder();" class="checkout-jdInt">去淘淘国际结算<b></b></a>
                          <a href="javascript:goToOrder();" class="checkout-jd">去淘淘结算<b></b></a>
                      </span>
                  </span>
              </div>
              <div class="total fr">
                  总计(不含运费):
                  <span class="totalSkuPrice">¥<fmt:formatNumber value="${totalPrice / 100}" maxFractionDigits="2" minFractionDigits="2" groupingUsed="true"/></span>
              </div>
          </div>
      </div></div>
</div><!-- cart-inner结束 -->
</div>
</div>
<!--推荐位html修改处-->


<script type="text/javascript" src="/js/base-v1.js"></script>
<!-- footer start -->
<jsp:include page="commons/footer.jsp" />
<!-- footer end -->

<!-- 购物车相关业务 -->
<script type="text/javascript" src="/js/cart.js"></script>
<script type="text/javascript" src="/js/jquery.price_format.2.0.min.js"></script>

</html>

购物车列表页面引用的 js:

var TTCart = {
    load : function(){ // 加载购物车数据
        
    },
    itemNumChange : function(){
        $(".increment").click(function(){//
            var _thisInput = $(this).siblings("input");
            _thisInput.val(eval(_thisInput.val()) + 1);
            $.post("/cart/add/"+_thisInput.attr("itemId")+".html?num=1",function(data){
                TTCart.refreshTotalPrice();
            });
        });
        $(".decrement").click(function(){//-
            var _thisInput = $(this).siblings("input");
            if(eval(_thisInput.val()) == 1){
                return ;
            }
            _thisInput.val(eval(_thisInput.val()) - 1);
            $.post("/cart/add/"+_thisInput.attr("itemId")+".html?num=-1",function(data){
                TTCart.refreshTotalPrice();
            });
        });
        $(".quantity-form .quantity-text").rnumber(1);//限制只能输入数字
        $(".quantity-form .quantity-text").change(function(){
            var _thisInput = $(this);
            $.post("/cart/update/"+_thisInput.attr("itemId")+".html?num="+_thisInput.val(),function(data){
                TTCart.refreshTotalPrice();
            });
        });
    },
    refreshTotalPrice : function(){ //重新计算总价
        var total = 0;
        $(".quantity-form .quantity-text").each(function(i,e){
            var _this = $(e);
            total += (eval(_this.attr("itemPrice")) * 10000 * eval(_this.val())) / 10000;
        });
        $(".totalSkuPrice").html(new Number(total/100).toFixed(2)).priceFormat({ //价格格式化插件
             prefix: '¥',
             thousandsSeparator: ',',
             centsLimit: 2
        });
    }
};

$(function(){
    TTCart.load();
    TTCart.itemNumChange();
});

上面代码没有解决的问题:

原文地址:https://www.cnblogs.com/libin6505/p/9878423.html