品優購項目記錄:day16

今日目標:

(1)理解品優購購物車的實現思路

(2)運用Cookie存儲購物車

(3)編寫購物車前端代碼

(4)運用 Redis 存儲購物車

 

目錄

1、購物車工程搭建

1.1 需求分析

1.2 工程搭建

2、Cookie存儲購物車

2.1 需求分析

2.2 後端-添加商品到購物車

2.3 購物車列表展示

2.4 商品數量加減

2.5 計算總金額和總數量

3、Redis 存儲購物車

3.1 需求分析

3.2 後端代碼

4、購物車合併

4.1 需求分析

4.2 後端


 

1、購物車工程搭建

 

1.1 需求分析

用戶在商品詳細頁點擊加入購物車,提交商品SKU編號和購買數量,添加到購物車。購物車展示頁面如下:

 

 

1.2 工程搭建

(1)參考之前的工程進行搭建(分別有:pinyougou-cart-interface、pinyougou-cart-service和pinyougou-cart-web),其中cart-web參考user-web

 

(2)創建購物車組合實體類

package com.pinyougou.pojogroup;

import com.pinyougou.pojo.TbOrderItem;

import java.io.Serializable;
import java.util.List;

/**
 * 購物車組合實體類
 * Author xushuai
 * Description
 */
public class Cart implements Serializable {

    /** 商家ID */
    private String sellerId;
    /** 商家名稱 */
    private String sellerName;
    /** 購物車商品明細列表 */
    private List<TbOrderItem> orderItemList;

}

 

 

 

2、Cookie存儲購物車

 

2.1 需求分析

使用cookie存儲購物車數據。服務層負責邏輯,控制層負責讀寫cookie 。

 

2.2 後端-添加商品到購物車

(1)服務層接口(cart-interface),新增CartService

package com.pinyougou.cart.service;

import com.pinyougou.pojogroup.Cart;

import java.util.List;

/**
 * 購物車接口
 * Author xushuai
 * Description
 */
public interface CartService {

    /**
     * 添加商品到購物車中
     *
     * @param cartList 購物車列表
     * @param itemId 商品ID
	 * @param num 添加的數量
     * @return java.util.List<com.pinyougou.pojogroup.Cart>
     */
    List<Cart> addGoodsToCartList(List<Cart> cartList, Long itemId, Integer num);
}

(2)服務層實現(cart-service),新增CartServiceImpl

package com.pinyougou.cart.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.pinyougou.cart.service.CartService;
import com.pinyougou.mapper.TbItemMapper;
import com.pinyougou.pojo.TbItem;
import com.pinyougou.pojo.TbOrderItem;
import com.pinyougou.pojogroup.Cart;
import exception.PinyougouException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 購物車實現
 * Author xushuai
 * Description
 */
@Service
@Transactional
public class CartServiceImpl implements CartService {

    @Autowired
    private TbItemMapper itemMapper;


    @Override
    public List<Cart> addGoodsToCartList(List<Cart> cartList, Long itemId, Integer num) {
        /*
         * 1.使用SKUID查詢SKU商品對象
         * 2.使用商品對象獲取商家信息
         * 3.根據商家ID在購物車列表中查詢購物車對象
         * 4.購物車列表中不存在該商家的購物車
         *      4.1 創建新的購物車對象,將新的購物車對象添加到購物車列表
         * 5.購物車列表中存在該商家的購物車
         *      5.1 判斷該購物車是否存在該商品的明細
         *          5.1.1 不存在,新增該明細到明細列表
         *          5.1.2 存在,在原有的數量上加上新增的數量,並更改金額
         */
        // 1.查詢SKU商品對象
        TbItem item = itemMapper.selectByPrimaryKey(itemId);
        if (item == null) {
            throw new PinyougouException("商品不存在!");
        }
        if (!item.getStatus().equals(TbItem.STATUS_NORMAL)) {
            throw new PinyougouException("商品狀態異常");
        }
        // 2.獲取商家信息
        String sellerId = item.getSellerId();
        String sellerName = item.getSeller();
        // 3.根據商家ID查詢購物車中的對象
        Cart cart = searchCartBySellerId(cartList, sellerId);
        if (cart == null) {// 4.購物車列表中不存在該商家的購物車
            // 創建購物車對象
            cart = new Cart();
            cart.setSellerId(sellerId);
            cart.setSellerName(sellerName);
            List<TbOrderItem> orderItemList = new ArrayList<>();
            // 使用item對象生成購物車明細
            TbOrderItem tbOrderItem = itemToOrderItem(item, num);
            orderItemList.add(tbOrderItem);
            cart.setOrderItemList(orderItemList);

            // 將購物車放入購物車列表
            cartList.add(cart);

        } else {// 5.購物車列表中存在該商家的購物車
            // 5.1 判斷該購物車是否存在該商品的明細
            TbOrderItem orderItem = searchOrderItemByItemId(cart.getOrderItemList(), item.getId());
            if (orderItem == null) {// 5.1.1 不存在,新增該明細到明細列表
                orderItem = itemToOrderItem(item, num);
                // 添加到明細列表
                cart.getOrderItemList().add(orderItem);
            } else {// 5.1.2 存在,在原有的數量上加上新增的數量,並更改金額
                // 判斷操作後的購物車情況
                if (orderItem.getNum() + num < 1) {// 數量小於1
                    // 移除該明細
                    cart.getOrderItemList().remove(orderItem);
                    if (cart.getOrderItemList().size() == 0) {// 明細列表中無數據
                        // 移除該購物車
                        cartList.remove(cart);
                    }
                }
                // 修改數量
                orderItem.setNum(orderItem.getNum() + num);
                // 修改金額
                orderItem.setTotalFee(BigDecimal.valueOf(orderItem.getPrice().doubleValue() * orderItem.getNum()));
            }
        }

        return cartList;
    }

    /**
     * 根據itemId查詢購物車明細列表
     *
     * @param orderItemList 購物車明細列表
     * @param itemId        商品ID
     * @return com.pinyougou.pojo.TbOrderItem
     */
    private TbOrderItem searchOrderItemByItemId(List<TbOrderItem> orderItemList, Long itemId) {
        // 遍歷購物車明細列表
        for (TbOrderItem orderItem : orderItemList) {
            if (orderItem.getItemId().longValue() == itemId.longValue()) {
                return orderItem;
            }
        }
        return null;
    }

    /**
     * 將item對象轉換爲OrderItem對象
     *
     * @param item 商品對象
     * @param num  數量
     * @return com.pinyougou.pojo.TbOrderItem
     */
    private TbOrderItem itemToOrderItem(TbItem item, Integer num) {
        TbOrderItem orderItem = new TbOrderItem();
        orderItem.setGoodsId(item.getGoodsId());
        orderItem.setItemId(item.getId());
        orderItem.setNum(num);
        orderItem.setPicPath(item.getImage());
        orderItem.setPrice(item.getPrice());
        orderItem.setSellerId(item.getSellerId());
        orderItem.setTitle(item.getTitle());
        orderItem.setTotalFee(BigDecimal.valueOf(item.getPrice().doubleValue() * num));

        return orderItem;
    }

    /**
     * 根據商家ID查詢購物車列表
     *
     * @param cartList 購物車列表
     * @param sellerId 商家ID
     * @return com.pinyougou.pojogroup.Cart
     */
    private Cart searchCartBySellerId(List<Cart> cartList, String sellerId) {
        // 遍歷購物車列表
        for (Cart cart : cartList) {
            if (cart.getSellerId().equals(sellerId)) {
                return cart;
            }
        }
        return null;
    }


}

(3)控制層(cart-web),新增CartController

package com.pinyougou.cart.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.pinyougou.cart.service.CartService;
import com.pinyougou.pojogroup.Cart;
import entity.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import util.CookieUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * 購物車控制層
 * Author xushuai
 * Description
 */
@RestController
@RequestMapping("/cart")
public class CartController {

    /** cookieName:cookie名稱 */
    private final String CARTLIST_COOKIENAME = "cartList";
    /** cookie_maxAge:cookie存活時間 */
    private final int MAXAGE_COOKIE = 3600 * 60;

    @Reference
    private CartService cartService;

    @Autowired
    private HttpServletRequest request;
    @Autowired
    private HttpServletResponse response;


    /**
     * 添加商品到購物車
     *
     * @param itemId 商品ID
	 * @param num 數量
     * @return entity.Result
     */
    @RequestMapping("/addGoodsToCartList")
    public Result addGoodsToCartList(Long itemId, Integer num) {
        try {
            List<Cart> cartList = findCartList();

            // 添加商品到購物車
            cartList = cartService.addGoodsToCartList(cartList, itemId, num);

            // 將購物車列表轉換爲json字符串
            String cookieValue = JSON.toJSONString(cartList);
            // 將購物車添加到cookie中
            CookieUtil.setCookie(request, response, CARTLIST_COOKIENAME, cookieValue, MAXAGE_COOKIE, "UTF-8");

            return Result.success("添加商品到購物車成功");
        }catch (Exception e){
            e.printStackTrace();
            return Result.error("添加商品到購物車失敗");
        }
    }

    /**
     * 獲取購物車列表
     *
     * @return java.util.List<com.pinyougou.pojogroup.Cart>
     */
    @RequestMapping("/findCartList")
    public List<Cart> findCartList() {
        // 從cookie中獲取購物車列表
        String cartListJson = CookieUtil.getCookieValue(request, CARTLIST_COOKIENAME, "UTF-8");
        List<Cart> cartList = JSON.parseArray(cartListJson, Cart.class);
        return cartList;
    }


}

 

 

 

2.3 購物車列表展示

(1)前端:編寫cartService.js

//購物車服務層
app.service('cartService', function ($http) {
    //購物車列表
    this.findCartList = function () {
        return $http.get('cart/findCartList.do');
    }
});

(2)前端:編寫cartController.js

//購物車控制層 
app.controller('cartController', function ($scope, cartService) {
    //查詢購物車列表
    $scope.findCartList = function () {
        cartService.findCartList().success(
            function (response) {
                $scope.cartList = response;
            }
        );
    }
});

(3)頁面引入JS文件和基礎指令,並初始化執行查詢購物車列表方法

(4)頁面綁定變量

(5)添加商品到購物車

(6)查看購物車

 

 

 

2.4 商品數量加減

(1)前端:在cartService.js中新增方法

    //添加商品到購物車
    this.addGoodsToCartList = function (itemId, num) {
        return $http.get('cart/addGoodsToCartList.do?itemId=' + itemId + '&num=' + num);
    }

(2)前端:在cartController.js中新增方法

    //添加商品到購物車
    $scope.addGoodsToCartList = function (itemId, num) {
        cartService.addGoodsToCartList(itemId, num).success(
            function (response) {
                if (response.success) {
                    $scope.findCartList();//刷新列表
                } else {
                    alert(response.message);//彈出錯誤提示
                }
            }
        );
    }

(3)前端:頁面 加減號 綁定單擊事件

 

 

2.5 計算總金額和總數量

(1)前端:在cartService.js中新增方法

    // 合計金額
    this.sum = function (cartList) {
        // 返回結果集
        var totalValue = {totalNum: 0, totalMoney: 0};
        // 遍歷購物車列表
        for (var i = 0; i < cartList.length; i++) {
            var cart = cartList[i];
            for (var j = 0; j < cart.orderItemList.length; j++) {
                // 累加數量
                totalValue.totalNum += cart.orderItemList[j].num;
                // 累加金額
                totalValue.totalMoney += cart.orderItemList[j].totalFee;
            }
        }
        return totalValue;
    }

(2)前端:在cartController.js中的findCartList中新增邏輯

(3)頁面綁定變量

 

 

 

 

 

3、Redis 存儲購物車

 

3.1 需求分析

判斷當前用戶是否登陸,如果未登錄採用Cookie存儲,如果登錄則採用Redis存儲。登錄後要進行Cookie購物車與Redis購物車的合併操作,並清除Cookie購物車。

 

3.2 後端代碼

(1)後端:修改放行cart/*.do的配置,將其配置爲匿名角色訪問權限

(2)後端:服務層接口(cart-interface),在CartService中新增方法

    /**
     * 從redis中獲取購物車列表
     *
     * @param
     * @return java.util.List<com.pinyougou.pojogroup.Cart>
     */
    List<Cart> findCartListFromRedis(String username);

    /**
     * 將購物車列表保存到redis中
     *
     * @param username 當前登錄用戶名
     * @param cartList 購物車列表
     */
    void saveCartListToRedis(String username, List<Cart> cartList);

(3)後端:服務層實現(cart-service),在CartServiceImpl中新增實現

    @Override
    public List<Cart> findCartListFromRedis(String username) {
        System.out.println("從redis中獲取當前用戶的購物車");
        // 從購物車中獲取
        List<Cart> cartList = (List<Cart>) redisTemplate.boundHashOps(REDIS_CARTLIST_KEY).get(username);
        if (cartList == null) {
            cartList = new ArrayList<>();
        }
        return cartList;
    }

    @Override
    public void saveCartListToRedis(String username, List<Cart> cartList) {
        System.out.println("將購物車存入redis中");
        // 將購物車保存到redis
        redisTemplate.boundHashOps(REDIS_CARTLIST_KEY).put(username, cartList);
    }

(4)後端:控制層修改findCartList和addGoodsToCartList方法

    /**
     * 添加商品到購物車
     *
     * @param itemId 商品ID
	 * @param num 數量
     * @return entity.Result
     */
    @RequestMapping("/addGoodsToCartList")
    public Result addGoodsToCartList(Long itemId, Integer num) {
        // 獲取當前登錄用戶名
        String loginUser = SecurityContextHolder.getContext().getAuthentication().getName();

        try {
            List<Cart> cartList = findCartList();
            // 添加商品到購物車
            cartList = cartService.addGoodsToCartList(cartList, itemId, num);

            // 判斷是否存入redis
            if (loginUser == ROLE_ANONYMOUSUSER) {// 未登錄
                // 將購物車列表轉換爲json字符串
                String cookieValue = JSON.toJSONString(cartList);
                // 將購物車添加到cookie中
                CookieUtil.setCookie(request, response, CARTLIST_COOKIENAME, cookieValue, MAXAGE_COOKIE, "UTF-8");
            } else {// 已登錄
                // 存入redis
                cartService.saveCartListToRedis(loginUser, cartList);
            }

            return Result.success("添加商品到購物車成功");
        }catch (Exception e){
            e.printStackTrace();
            return Result.error("添加商品到購物車失敗");
        }
    }

    /**
     * 獲取購物車列表
     *
     * @return java.util.List<com.pinyougou.pojogroup.Cart>
     */
    @RequestMapping("/findCartList")
    public List<Cart> findCartList() {
        // 獲取當前登錄用戶名
        String loginUser = SecurityContextHolder.getContext().getAuthentication().getName();
        // 判斷是否爲匿名權限
        if (loginUser.equals(ROLE_ANONYMOUSUSER)) {// 爲匿名權限,未登錄狀態
            // 從cookie中獲取購物車列表
            String cartListJson = CookieUtil.getCookieValue(request, CARTLIST_COOKIENAME, "UTF-8");
            if (cartListJson == null || cartListJson.equals("")) {
                cartListJson = "[]";
            }
            List<Cart> cartList_cookie = JSON.parseArray(cartListJson, Cart.class);
            return cartList_cookie;
        } else {// 不是匿名權限,登錄狀態
            // 從redis中獲取購物車列表
            List<Cart> cartList_redis = cartService.findCartListFromRedis(loginUser);
            return cartList_redis;
        }
    }

(5)單點登錄對接購物車

 

 

 

4、購物車合併

 

4.1 需求分析

當登錄成功時,將cookie購物車中的購物車列表和redis中的購物車列表進行合併

 

 

4.2 後端

(1)服務層接口(cart-interface),新增方法

    /**
     * 合併購物車
     *
     * @param cartList1 購物車1
	 * @param cartList2 購物車2
     * @return java.util.List<com.pinyougou.pojogroup.Cart>
     */
    List<Cart> mergeCartList(List<Cart> cartList1, List<Cart> cartList2);

(2)服務層實現(cart-service),新增實現

    @Override
    public List<Cart> mergeCartList(List<Cart> cartList1, List<Cart> cartList2) {
        // 遍歷任意購物車
        for (Cart cart : cartList1) {
            // 遍歷購物車明細列表
            for (TbOrderItem orderItem : cart.getOrderItemList()) {
                // 進行合併操作
                cartList2 = addGoodsToCartList(cartList2, orderItem.getItemId(), orderItem.getNum());
            }
        }
        return cartList2;
    }

(3)控制層,修改findCartList方法中的邏輯

    /**
     * 獲取購物車列表
     *
     * @return java.util.List<com.pinyougou.pojogroup.Cart>
     */
    @RequestMapping("/findCartList")
    public List<Cart> findCartList() {
        // 獲取當前登錄用戶名
        String loginUser = SecurityContextHolder.getContext().getAuthentication().getName();
        // 從cookie中獲取購物車列表
        String cartListJson = CookieUtil.getCookieValue(request, CARTLIST_COOKIENAME, "UTF-8");
        if (cartListJson == null || cartListJson.equals("")) {
            cartListJson = "[]";
        }
        List<Cart> cartList_cookie = JSON.parseArray(cartListJson, Cart.class);
        // 判斷是否爲匿名權限
        if (loginUser.equals(ROLE_ANONYMOUSUSER)) {// 爲匿名權限,未登錄狀態

            return cartList_cookie;
        } else {// 不是匿名權限,登錄狀態
            // 從redis中獲取購物車列表
            List<Cart> cartList_redis = cartService.findCartListFromRedis(loginUser);
            // cookie購物車中存在數據
            if (cartList_cookie.size() > 0) {
                // 進行購物車合併
                cartList_redis = cartService.mergeCartList(cartList_cookie, cartList_redis);
                // 清除cookie中的購物車數據
                CookieUtil.deleteCookie(request, response, CARTLIST_COOKIENAME);
                // 將合併後的購物車數據存入reids
                cartService.saveCartListToRedis(loginUser, cartList_redis);
            }

            return cartList_redis;
        }
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章