移动商城第十七篇【购物车增删改查】

286 阅读5分钟

tags: 移动商城项目


把商品加入购物车

接下来我们要做的就是将商品加入到购物车中。我们这次使用的是Cookie来将用户的信息存储起来。那为什么要用cookie呢??

  • 如果将购物车存储在Session,那么Session里边的值容易丢失。
  • 存储在Cookie中,用户不需要登陆就能够查看得到购物车的数据。

那我们现在决定将购物车存储在Cookie中了,那Cookie中保存的是怎么样的字符串数据呢???

  • 显而易见我们第一时间想到的就是JSON

JSON能够很好地将字符串转成Java对象,将Java对象转成JSON给浏览器进行显示!

看回我们的加入购物车,将什么数据加入进去呢???

我们可以将数量和SkuId加入进去就行了。有了SkuId就可以获取商品类的所有数据了!

加入购物车之前

在加入购物车之前我们需要做两件事:

-** 判断Cookie是否被禁用了**【我们使用Cookie来进行保存购物车数据的、Cookie不能被禁用!】

  • 判断库存是否充足【在加入之前、查询一次库存是否足够!】

判断Cookie是否被禁用了:



    /**
     * 校验Cookie是否被禁用了。
     *
     * 其实就是新建一个Cookie,然后是否能获取得到Cookie的值。
     *  如果可以得到,那么就是Cookie没有被禁用
     *  如果没有得到,那么Cookie就被禁用了。
     * @param request
     * @param response
     * @return
     */
    String validCookie(HttpServletRequest request, HttpServletResponse response);


    public String validCookie(HttpServletRequest request, HttpServletResponse response) {

        //默认被禁用
        String result = "ban";

        //只要是本主机下的,Cookie都会被发布出去
        Cookie cookie = new Cookie("test", "test");
        cookie.setPath("/");
        response.addCookie(cookie);

        //查看是否能获取得到Cookie
        Cookie[] cookies = request.getCookies();

        if (cookies != null && cookies.length > 0) {
            for (Cookie cookie1 : cookies) {
                String name = cookie1.getName();
                String value = cookie1.getValue();
                /**
                 * 如果都拿到,那么Cookie就没有被禁用!
                 */
                if (name.equals("test") && value.equals("test")) {

                    result = "noBan";
                    return result;
                }
            }
        }
        return result;
    }

    @RequestMapping("/validateCookie.do")
    public void  validateCookie(HttpServletRequest request, HttpServletResponse response, PrintWriter writer) {
        String result = cartService.validCookie(request, response);
        writer.write(result);
    }

判断库存是否充足:

    @RequestMapping("/validateStock.do")
    public void validateStock(Long SkuId, Integer quantity,PrintWriter writer) {

        String result = "noStock";
        EbSku sku = skuService.selectByPrimaryKey(SkuId);
        //判断数量多还是库存多
        if (sku.getStockInventory() > quantity) {
            result = "hasStock";
        }
        writer.write(result);
    }

在页面上通过class属性和自定义id来获取页面上的库存和数量!

前台页面的代码如下:


        //加入购物车之前,判断库存和cookie
        function addCart() {

            var cookieResult = validateCookie();
            if (cookieResult == "ban") {
                alert("Cookie被禁用了,无法加入购物车");
                return;
            }
            //在页面上获取得到对应的skuId和数量
            var skuId = null ;
            $("#skuChange a").each(function(){
                var clazz = $(this).attr("class");
                if(clazz == "here"){
                    skuId = $(this).attr("skuId");
                }
            });
            var quantity = $("#quantity").val();
            var StockResult = validateStock(skuId,quantity);
            if (StockResult == "noStock") {
                alert("库存已经不足,无法加入购物车");
                return;
            }
            window.location.href = "http://localhost:8080/portal/cart/addCart.do";
        }
        function validateCookie() {
            var result = "";
            $.ajax({
                url: "http://localhost:8080/portal/cart/validateCookie.do",
                type: "post",
                async:false,
                success:function (responseText) {
                    result =  responseText
                },
                error:function () {
                    alert("系统错误");
                }
            });
            return result;
        }
        function validateStock(skuId,quantity) {
            var result = "";
            $.ajax({
                url: "http://localhost:8080/portal/cart/validateStock.do",
                data:{
                    skuId:skuId,
                    quantity:quantity
                },
                type: "post",
                async:false,
                success:function (responseText) {
                    result =  responseText
                },
                error:function () {
                    alert("系统错误");
                }
            });
            return result;
        }

将数据拼接成Cookie保存起来

在前台中已经通过ajax调用service来判断是否有库存和cookie是否被禁用了。接下来就将我们的skuId和quantity拼接成Cookie保存起来。也是使用ajax来将数据带过去


            //将skuId和quantity带过去给服务器
            $.ajax({
                url: "http://localhost:8080/portal/cart/addCart.do",
                data:{
                    skuId:skuId,
                    quantity:quantity
                },
                type: "post",
                success:function (responseText) {
                     if(responseText=="addSuccess"){
                         alert("成功添加到购物车中!");
                     }
                },
                error:function () {
                    alert("系统错误");
                }
            });

编写service添加购物车



    /**
     * 添加购物车,使用Cookie保存起来!
     *
     * 使用到Cookie的话,那么就需要用到request和response对象了。
     * @param request
     * @param response
     */
    void  addCart(HttpServletRequest request, HttpServletResponse response,Long skuId, Integer quantity);

把商品添加购物车中也有好几种情况:

  • 用户没有购物车
  • 购物车的商品已存在
  • 购物车的商品不存在

接下来我们来去看看购物车页面是怎么样的:

只有知道了购物车展示页面我们才知道我们的购物车实体是怎么设计的

从图上我们可以知道大多数的数据都是Sku中的,还有商品的编号和商品的名称。

于是,我们可以使用Sku作为主体,与Item来进行关联就行了。于是乎,我们可以设计购物车实体是这样的:

public class EbCart {

    private Long skuId;
    private Integer quantity;

    private EbSku sku;

    public Long getSkuId() {
        return skuId;
    }
    public void setSkuId(Long skuId) {
        this.skuId = skuId;
    }

    public Integer getQuantity() {
        return quantity;
    }

    public void setQuantity(Integer quantity) {
        this.quantity = quantity;
    }

    public EbSku getSku() {
        return sku;
    }

    public void setSku(EbSku sku) {
        this.sku = sku;
    }
}


sku实体要与Item进行关联:



    //与Item进行关联
    private EbItem item;
    public EbItem getItem() {
        return item;
    }
    public void setItem(EbItem item) {
        this.item = item;
    }

根据cookie的三种情况写service业务逻辑


 public void addCart(HttpServletRequest request, HttpServletResponse response, Long skuId, Integer quantity) {

        List<EbCart> cartList = null;

        //json的配置对象
        JsonConfig jc = new JsonConfig();
        //设置要转换的类
        jc.setRootClass(EbCart.class);
        //设置不需要转换的属性
        jc.setExcludes(new String[]{"sku"});

        Cookie[] cookies = request.getCookies();
        if (cookies != null && cookies.length > 0) {
            for (Cookie c : cookies) {
                String name = c.getName();

                //读取购物车的key,在配置文件中保存起来了。
                String cart_key = ResourcesUtils.readProp("cart_key");
                if (StringUtils.equalsIgnoreCase(name, cart_key)) {
                    //得到cookie里边的值【JSON格式的数组】
                    String value = c.getValue();

                    //将JSON数组转成是Java对象
                    JSONArray ja = JSONArray.fromObject(value);
                    cartList = (List<EbCart>) JSONSerializer.toJava(ja, jc);

                    //判断要添加的商品在购物车是否存在
                    String result = "noExist";
                    for (EbCart cart : cartList) {
                        //购物车中已存在
                        if (cart.getSkuId() == skuId) {
                            cart.setQuantity(cart.getQuantity() + quantity);
                            result = "exist";
                        }
                    }
                    //购物车中的商品不存在
                    if (StringUtils.equalsIgnoreCase("noExist", result)) {
                        EbCart ebCart = new EbCart();
                        ebCart.setQuantity(quantity);
                        ebCart.setSkuId(skuId);
                        cartList.add(ebCart);
                    }
                }
            }
        }
        //上边已经判断了购物车存在,商品是否存在的两种情况了。以下是判断购物车是否存在的问题
        //如果上边的cookie为null,转换不了List集合的话,那么我们的List集合是为空的。List集合为空的话,那么我们的购物车是不存在的。
        if (cartList == null || cartList.size() == 0) {
            cartList = new ArrayList<EbCart>();
            EbCart ebCart = new EbCart();
            ebCart.setQuantity(quantity);
            ebCart.setSkuId(skuId);
            cartList.add(ebCart);
        }
        
        //最后将我们的Java对象重新转成JSON,将Cookie更新
       	JSONArray ja = JSONArray.fromObject(cartList, jc);
        String result = ja.toString();
        Cookie cookie = new Cookie("cart_key", result);
        cookie.setMaxAge(Integer.MAX_VALUE);
        cookie.setPath("/");
        response.addCookie(cookie);
        
    }

查看购物车

查看购物车并不难,和添加购物车一样。都是将Cookie的值转成是Java对象,然后将Java对象返回给页面做展示就行了

  • 要做的就是将购物车商品的信息详细查询出来!

通过skuId查询出具体的商品信息。


    EbSku selectByPrimaryKeyForDetail(Long skuId);

mapper:

  <resultMap id="detailMap" type="com.rl.ecps.model.EbSku" extends="BaseResultMap">
    <association property="item" javaType="com.rl.ecps.model.EbItem">
      <id column="ITEM_ID" property="itemId" jdbcType="DECIMAL"/>
      <result column="ITEM_NAME" property="itemName" jdbcType="VARCHAR"/>
      <result column="ITEM_NO" property="itemNo" jdbcType="VARCHAR"/>
      <result column="BRAND_ID" property="brandId" jdbcType="DECIMAL"/>
      <result column="CAT_ID" property="catId" jdbcType="DECIMAL"/>
      <result column="TAG_IMG_ID" property="tagImgId" jdbcType="DECIMAL"/>
      <result column="TAG_IMG" property="tagImg" jdbcType="DECIMAL"/>
      <result column="IS_NEW" property="isNew" jdbcType="DECIMAL"/>
      <result column="IS_GOOD" property="isGood" jdbcType="DECIMAL"/>
      <result column="IS_HOT" property="isHot" jdbcType="DECIMAL"/>
      <result column="PROMOTION" property="promotion" jdbcType="VARCHAR"/>
      <result column="AUDIT_STATUS" property="auditStatus" jdbcType="DECIMAL"/>
      <result column="SHOW_STATUS" property="showStatus" jdbcType="DECIMAL"/>
      <result column="IMGS" property="imgs" jdbcType="VARCHAR"/>
      <result column="KEYWORDS" property="keywords" jdbcType="VARCHAR"/>
      <result column="PAGE_DESC" property="pageDesc" jdbcType="VARCHAR"/>
      <result column="ITEM_RECYCLE" property="itemRecycle" jdbcType="DECIMAL"/>
      <result column="ON_SALE_TIME" property="onSaleTime" jdbcType="TIMESTAMP"/>
      <result column="CHECK_TIME" property="checkTime" jdbcType="TIMESTAMP"/>
      <result column="UPDATE_TIME" property="updateTime" jdbcType="TIMESTAMP"/>
      <result column="UPDATE_USER_ID" property="updateUserId" jdbcType="DECIMAL"/>
      <result column="CREATE_TIME" property="createTime" jdbcType="TIMESTAMP"/>
      <result column="CHECKER_USER_ID" property="checkerUserId" jdbcType="DECIMAL"/>
      <result column="FULL_PATH_DEPLOY" property="fullPathDeploy" jdbcType="VARCHAR"/>
      <result column="FULL_PATH_DEPLOY_OFFER" property="fullPathDeployOffer" jdbcType="VARCHAR"/>
      <result column="ORIGINAL_ITEM_ID" property="originalItemId" jdbcType="DECIMAL"/>
      <result column="LAST_STATUS" property="lastStatus" jdbcType="DECIMAL"/>
      <result column="MERCHANT_ID" property="merchantId" jdbcType="DECIMAL"/>
      <result column="ITEM_SORT" property="itemSort" jdbcType="DECIMAL"/>
      <result column="SALES" property="sales" jdbcType="DECIMAL"/>
      <result column="CREATE_USER_ID" property="createUserId" jdbcType="DECIMAL"/>
      <result column="SIM_LEVEL" property="simLevel" jdbcType="DECIMAL"/>
      <result column="GIFT_DESC" property="giftDesc" jdbcType="VARCHAR"/>
      <result column="GIFT_IMG" property="giftImg" jdbcType="VARCHAR"/>
      <result column="GIFT_SHOW_TYPE" property="giftShowType" jdbcType="VARCHAR"/>
      <result column="IMG_SIZE1" property="imgSize1" jdbcType="VARCHAR"/>
    </association>
  </resultMap>

  <select id="selectByPrimaryKeyForDetail" parameterType="long" resultMap="detailMap">

    SELECT *
    FROM EB_SKU sku, EB_ITEM item
    WHERE item.ITEM_ID = sku.ITEM_ID
          AND sku.SKU_ID = #{skuId}
  </select>

service查询购物车数据:


    public List<EbCart> listCart(HttpServletRequest request, HttpServletResponse response) {

        List<EbCart> cartList = null;

        //json的配置对象
        JsonConfig jc = new JsonConfig();
        //设置要转换的类
        jc.setRootClass(EbCart.class);
        //设置不需要转换的属性
        jc.setExcludes(new String[]{"sku"});

        Cookie[] cookies = request.getCookies();
        if (cookies != null && cookies.length > 0) {
            for (Cookie c : cookies) {
                String name = c.getName();

                //读取购物车的key,在配置文件中保存起来了。
                String cart_key = ResourcesUtils.readProp("cart_key");
                if (StringUtils.equalsIgnoreCase(name, cart_key)) {
                    //得到cookie里边的值【JSON格式的数组】
                    String value = c.getValue();

                    //将JSON数组转成是Java对象
                    JSONArray ja = JSONArray.fromObject(value);
                    cartList = (List<EbCart>) JSONSerializer.toJava(ja, jc);

                    //根据购物车中商品的id获取详细信息
                    for (EbCart cart : cartList) {
                        Long skuId = cart.getSkuId();
                        EbSku sku = skuService.selectByPrimaryKeyForDetail(skuId);
                        cart.setSku(sku);
                    }
                }
            }
        }
        return cartList;

    }

controller查询出商品的数量、购物车总价、返回给页面展示:


    @RequestMapping("/listCart.do")
    public String listCart(HttpServletRequest request, HttpServletResponse response, Model model) {

        List<EbCart> carts = cartService.listCart(request, response);

        //算出购物车总价和商品数量
        int itemNum = 0;
        BigDecimal totalPrice = new BigDecimal(0);
        for (EbCart cart : carts) {
            totalPrice = totalPrice.add(cart.getSku().getSkuPrice().multiply(new BigDecimal(cart.getQuantity())));

            itemNum++;
        }
        model.addAttribute("carts", carts);
        model.addAttribute("totalPrice",totalPrice);
        model.addAttribute("itemNum",itemNum);
        return "shop/car";
    }

页面展示效果:

微调数量

我们可以在页面上微调数量的。

当点击+号的时候,数量+1,当点击-号的时候,数量-1

由于我们数量的改变会导致金钱的改变,可以直接就使用页面刷新的方法来干了!因为使用Ajax的话还要去替换那些值。

对其绑定事件、交由Controller处理


function reduceNum(skuId,quantity) {

	//在减少之前,校验一下库存
	//得到对应数量框
	var val = $("#quantity").val();
	val--;

	var validateResult = validateStock(skuId,val);

	console.log(validateResult);
	if(validateResult=="noStock"){
		alert("没有库存了!");
		return ;
	}
	$("#quantity").val(val);


	//返回给后台进行页面刷新。
	window.location.href = "${path}/cart/updateQuantity.do?skuId="+skuId+"&quantity="+val;
}
function addNum(skuId,quantity) {

	//在减少之前,校验一下库存
	//得到对应数量框
	var val = $("#quantity").val();
	val++;

	var validateResult = validateStock(skuId,val);

	console.log(validateResult);
	if(validateResult=="noStock"){
		alert("没有库存了!");
		return ;
	}
	$("#quantity").val(val);


	//返回给后台进行页面刷新。
	window.location.href = "${path}/cart/updateQuantity.do?skuId="+skuId+"&quantity="+val;
}

编写更新数量的service方法:

  • 先把cookie转成是java对象
  • 判断是否有对应的skuId值,如果有,那么我们修改其数量即可。
  • 重写Cookie返回给浏览器


    public void updateQuantity(HttpServletRequest request, HttpServletResponse response, Long skuId, Integer quantity) {

        List<EbCart> cartList = null;

        //json的配置对象
        JsonConfig jc = new JsonConfig();
        //设置要转换的类
        jc.setRootClass(EbCart.class);
        //设置不需要转换的属性
        jc.setExcludes(new String[]{"sku"});

        Cookie[] cookies = request.getCookies();
        if (cookies != null && cookies.length > 0) {
            for (Cookie c : cookies) {
                String name = c.getName();

                //读取购物车的key,在配置文件中保存起来了。
                String cart_key = ResourcesUtils.readProp("cart_key");
                if (StringUtils.equalsIgnoreCase(name, cart_key)) {
                    //得到cookie里边的值【JSON格式的数组】
                    String value = c.getValue();

                    //将JSON数组转成是Java对象
                    JSONArray ja = JSONArray.fromObject(value);
                    cartList = (List<EbCart>) JSONSerializer.toJava(ja, jc);

                    //根据购物车中商品的id获取详细信息
                    for (EbCart cart : cartList) {
                        Long cartSkuId = cart.getSkuId();

                        //找到对应购物车中的商品,这里要使用longValue对数值进行比较。直接双等于是没有用的。
                        if (skuId.longValue() == cartSkuId.longValue()) {
                            cart.setQuantity(quantity);
                        }
                    }
                }
            }
        }
        //最后将我们的Java对象重新转成JSON,将Cookie更新
        JSONArray ja = JSONArray.fromObject(cartList, jc);
        String result = ja.toString();
        Cookie cookie = new Cookie("cart_key", result);
        cookie.setMaxAge(Integer.MAX_VALUE);
        cookie.setPath("/");
        response.addCookie(cookie);


    }

controller调用service的方法,重定向到购物车页面。那么我们的购物车页面拿到的就是最新的数据!



    @RequestMapping("/updateQuantity.do")
    public String updateQuantity(Long skuId, Integer quantity,HttpServletRequest request, HttpServletResponse response) {
        cartService.updateQuantity(request, response, skuId, quantity);

        return "redirect:/cart/listCart.do";
    }

#总结 #

  • 我们将购物车的数据存储在Cookie中,那么即使用户不登陆也能查看得到购物车的数据
  • Cookie存储的是JSON值,可以通过JsonArray来对JSON和Java对象之间的转换。很好用!
  • 在添加商品到购物车中的时候分为三种情况
    • 购物车存在,加入的商品在购物车中也存在
    • 购物车存在,加入的商品在购物车中不存在
    • 购物车不存在。
  • 我们可以拿到Cookie来解决前两种情况,第三种情况可以根据Cookie转成Java集合时来对其判断。如果Cookie不存在(购物车不存在)、那么转成的Java集合一定为null。
  • 在Cookie保存的数据是skuId和quantity,由于在购物车中需要显示有关商品和价钱之类的数据。我们主要显示的价钱的数据,那么我们在设计购物车实体的时候就使用了Sku来关联Item的数据!
  • 当Java对象解析成Cookie的时候,是不用把我们的Sku属性算进去的。
  • 无论是增改查,都是将Cookie获取出来,转成是Java对象、对Java对象进行修改[添加],最后重写Cookie

如果您觉得这篇文章帮助到了您,可以给作者一点鼓励