購物車功能實現


一、購物車的存儲形式

1、cookie存放數據

         無須登錄、無須查庫、保存在瀏覽器端

         優點:性能好、訪問快、沒有和數據庫交互。

          缺點1:換瀏覽器購物車數據會丟失。

          缺點2:電腦被他人使用,存在隱私安全。

2、session存放數據

         用戶登錄后,購物車數據放入用戶會話

         優點:初期性能較好、訪問快。

          缺點1:session基於內存、用戶量龐大影響服務器性能。

          缺點2:只能存在於當前回話,不適用集群與分布式系統。

3、數據庫存放數據

         用戶登錄后,購物車數據存入數據庫

        優點:數據持久化,可在任何地點任何時間訪問。

         缺點:頻繁讀寫數據庫,造成數據庫壓力。

4、Redis存放數據

          用戶登錄后,購物車數據存入redis緩存

        優點1:數據持久化,可以在任何地點任何時間訪問。

       優點2:頻繁讀寫只基於緩存,不會造成數據庫壓力。

       優點3:適用於集群與分布式系統,可擴展性強

 

系統使用的是cookie+redis的形式,用戶未登陸用的是cookie,登陸后用的cookie+redis相互結合

 

二、未登錄已登錄加入購物車業務代碼

    1、前端vue構建購物車的商品對象

         

     2、前端購物車的數據覆蓋本地的cookie

          

    3、前端是在這里調用后端服務的。傳遞了shopcartItem這個對象。

     

     3、服務端

          1) 創建ShopcartBO對象

          

        

package com.imooc.pojo.bo;

public class ShopcartBO {

    private  String itemId;
    private  String itemImgUrl;
    private  String itemName;
    private  String specId;
    private  String specName;
    private  Integer buyCounts;
    private  String priceDiscount;
    private  String priceNormal;

    public String getItemId() {
        return itemId;
    }

    public void setItemId(String itemId) {
        this.itemId = itemId;
    }

    public String getItemImgUrl() {
        return itemImgUrl;
    }

    public void setItemImgUrl(String itemImgUrl) {
        this.itemImgUrl = itemImgUrl;
    }

    public String getItemName() {
        return itemName;
    }

    public void setItemName(String itemName) {
        this.itemName = itemName;
    }

    public String getSpecId() {
        return specId;
    }

    public void setSpecId(String specId) {
        this.specId = specId;
    }

    public String getSpecName() {
        return specName;
    }

    public void setSpecName(String specName) {
        this.specName = specName;
    }

    public Integer getBuyCounts() {
        return buyCounts;
    }

    public void setBuyCounts(Integer buyCounts) {
        this.buyCounts = buyCounts;
    }

    public String getPriceDiscount() {
        return priceDiscount;
    }

    public void setPriceDiscount(String priceDiscount) {
        this.priceDiscount = priceDiscount;
    }

    public String getPriceNormal() {
        return priceNormal;
    }

    public void setPriceNormal(String priceNormal) {
        this.priceNormal = priceNormal;
    }

    @Override
    public String toString() {
        return "ShopcartBO{" +
                "itemId='" + itemId + '\'' +
                ", itemImgUrl='" + itemImgUrl + '\'' +
                ", itemName='" + itemName + '\'' +
                ", specId='" + specId + '\'' +
                ", specName='" + specName + '\'' +
                ", buyCounts=" + buyCounts +
                ", priceDiscount='" + priceDiscount + '\'' +
                ", priceNormal='" + priceNormal + '\'' +
                '}';
    }
}
View Code

      2)添加商品到購物車

         

       3、  后端方法設計到cookie。那么就會用到request對象。

         

package com.imooc.controller;

import com.imooc.pojo.bo.ShopcartBO;
import com.imooc.utils.IMOOCJSONResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;


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


@Api(value = "購物車接口controller",tags = {"購物車接口相關的api"})
@RequestMapping("shopcart")
@RestController
public class ShopcartController {

    @ApiOperation(value = "添加商品到購物車",notes = "添加商品到購物車",httpMethod = "POST")
    @PostMapping("/add")
    public IMOOCJSONResult add(
            @RequestParam String userId,
            @RequestBody ShopcartBO shopcartBO,
            HttpServletRequest request,
            HttpServletResponse response
            ) {
           if (StringUtils.isBlank(userId)) {
             return   IMOOCJSONResult.errorMsg("");
           }
        System.out.println(shopcartBO);
           //TODO 前端用戶在登錄的情況下,添加商品到購物車,會同時在后端同步購物車到redis緩存

        return IMOOCJSONResult.ok();

    }

    @ApiOperation(value = "從購物車中刪除商品",notes = "從購物車中刪除商品",httpMethod = "POST")
    @PostMapping("/del")
    public IMOOCJSONResult del(
            @RequestParam String userId,
            @RequestParam String itemSpecId,
            HttpServletRequest request,
            HttpServletResponse response
    ) {
        if (StringUtils.isBlank(userId) || StringUtils.isBlank(itemSpecId)) {
            return   IMOOCJSONResult.errorMsg("");
        }

        //TODO 用戶在頁面刪除購物車中的商品數據,如果此時用戶已經登錄,則需要同步刪除后端購物車中的數據

        return IMOOCJSONResult.ok();

    }
}
View Code

      

   待完善方法體

        登陸后后端的接口要判斷相應的權限等等,那么這個權限又和redis,分布式會話有關,並且還涉及到攔截器。這些內容我們都會在分布式緩存里面所涉及到。

   完善用戶登陸的TODO

   

  

package com.imooc.controller;
import com.imooc.pojo.Users;
import com.imooc.pojo.bo.UserBO;
import com.imooc.service.UserService;
import com.imooc.utils.CookieUtils;
import com.imooc.utils.IMOOCJSONResult;
import com.imooc.utils.JsonUtils;
import com.imooc.utils.MD5Utils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

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

@Api(value = "注冊登錄",tags = "用於注冊和登錄的相關接口")
@RestController
@RequestMapping("passport")
public class PassportController {

    @Autowired
    private UserService userService;

    @ApiOperation(value="用戶名是否存在",notes = "用戶名是否存在",httpMethod = "GET")
    @GetMapping("/usernameIsExist")
    public IMOOCJSONResult usernameIsExist(@RequestParam String username){
         //1.
        if(StringUtils.isBlank(username)) {
            return IMOOCJSONResult.errorMsg("用戶名不能為空");
        }
        //2.
        boolean isExist=userService.queryUsernameIsExist(username);
        if (isExist) {
            return IMOOCJSONResult.errorMsg("用戶名已經存在");
        }
        //3.請求成功
        return IMOOCJSONResult.ok();
    }

    @ApiOperation(value="用戶注冊",notes = "用戶注冊",httpMethod = "POST")
    @PostMapping("/regist")
    public IMOOCJSONResult regist(@RequestBody UserBO userBO){
        String username = userBO.getUsername();
        String password = userBO.getPassword();
        String confirmPwd=userBO.getConfirmPassword();

          //0
        if(StringUtils.isBlank(username) ||
                StringUtils.isBlank(password)||
                StringUtils.isBlank(confirmPwd)){
            return IMOOCJSONResult.errorMsg("用戶名或密碼不能為空");
        }

         //1
        boolean isExist=userService.queryUsernameIsExist(username);
        if (isExist) {
            return IMOOCJSONResult.errorMsg("用戶名已經存在");
        }
        //2
          if(password.length()<6) {
              return IMOOCJSONResult.errorMsg("用戶密碼不能少於6位");
          }
        //3
        //2
        if(!password.equals(confirmPwd)) {
            return IMOOCJSONResult.errorMsg("兩次密碼不一致");
        }
        //4
         userService.creatUser(userBO);

        //TODO 生成用戶token,存入redis
        //TODO 同步購物車數據

        return IMOOCJSONResult.ok();
    }

    @ApiOperation(value="用戶登錄",notes = "用戶登錄",httpMethod = "POST")
    @PostMapping("/login")
    public IMOOCJSONResult login(@RequestBody UserBO userBO,
                                 HttpServletRequest request,
                                 HttpServletResponse response) throws Exception{
        String username = userBO.getUsername();
        String password = userBO.getPassword();
        //String confirmPwd=userBO.getConfirmPassword();

        //0
        if(StringUtils.isBlank(username) ||
                StringUtils.isBlank(password)
                ){
            return IMOOCJSONResult.errorMsg("用戶名或密碼不能為空");
        }
       Users user= userService.queryUserForLogin(username,
               MD5Utils.getMD5Str(password));

        if(user==null) {
            return IMOOCJSONResult.errorMsg("用戶名和密碼不正確");
        }

        user=setNullProperty(user);

        CookieUtils.setCookie(request, response,"user",
                JsonUtils.objectToJson(user),true);

        //TODO 生成用戶token,存入redis
        //TODO 同步購物車數據
        return IMOOCJSONResult.ok(user);
    }

    @ApiOperation(value="用戶退出登錄",notes = "用戶退出登錄",httpMethod = "POST")
    @PostMapping("/logout")
    public IMOOCJSONResult logout(@RequestParam String userId,HttpServletRequest request, HttpServletResponse response){

        //1
        CookieUtils.deleteCookie(request, response, "user");
        //TODO 用戶退出登錄,需要清空購物車
        //TODO 分布式會話中需要清除用戶數據
        //2
        return IMOOCJSONResult.ok();
    }
     private  Users setNullProperty(Users user)
     {
         user.setPassword(null);
         user.setNickname(null);
         user.setCreatedTime(null);
         return user;

     }

}
View Code

 

三、刷新購物車

 cookie中的數據拿出來在頁面上做渲染是可以的嗎?答案是不可以。這是因為我們的數據保存在前端,它只是一種臨時的數據。購物車里面的數據,它不可能馬上去結算去買單的。他有可能明天后天甚至過一個禮拜再打開。那么再打開購物車的時候,價格還是cookie里面的價格。當用戶進入到購物車這個頁面的時候,我們一定要刷新一下購物車里面的商品數據。如果說價格發生了更改,商品的圖片、規則、名稱都發生更改的話,我們就需要重新的刷新相關的數據。商品的數量是不需要做更新。尤其是金額需要做刷新。所以我們要把相應的數據,尤其是購物車里規格的id發發送到后端。讓后端去查詢出來購物車相關的數據,再放到頁面上展示。

  1、前端業務

      (1)在聲明周期函數里面找到renderShopcart方法,首先獲取cookie中購物車的數據,如果沒有就返回空

           

       (2)for循環拼接購物車的數據

            

     拼接完就是以逗號分隔開的字符串,如下: 1001,1002,3003,4004

    (3)請求后端的接口

        

   2、后端接口

        (1)我們要查的就是購物車里面的對象。除了buyCounts其余的內容我們都需要。

            

     (2)自定義sql查詢語句

           

          

SELECT
    i.id AS itemId,
    ii.url AS itemImgUrl,
    i.item_name AS itemName,
    sp.id AS specId,
    sp.`name` AS specName,
    sp.price_discount AS priceDiscount,
    sp.price_normal AS priceNormal 
FROM
    items_spec sp
    LEFT JOIN items i ON i.id = sp.item_id
    LEFT JOIN items_img ii ON i.id = ii.item_id 
WHERE
    ii.is_main = 1 
    AND sp.id IN (
        'bingan-1001-spec-1',
    'bingan-1001-spec-2',
    'bingan-1001-spec-3')
View Code

       (3)把sql復制到自定義的mapper里面。我們要返回的VO類型和之前寫好的ShopcartBO基本是一樣的,除了bugCounts這個屬性沒有。

傳入的結合對象命名為paramsList,標簽的閉合,循環的內容要在括號內部。里面的每一項元素使用逗號進行間隔。

       

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.imooc.mapper.ItemsMapperCustom" >
  <select id="queryItemComments" parameterType="Map" resultType="com.imooc.pojo.vo.ItemCommentVO">
      SELECT
          ic.comment_level AS commentLevel,
          ic.content AS content,
          ic.sepc_name AS specName,
          ic.created_time AS createdTime,
          u.face AS userFace,
          u.nickname AS nickName
      FROM
          items_comments ic
          LEFT JOIN users u ON ic.user_id = u.id
      WHERE
          ic.item_id = #{paramsMap.itemId}
        <if test=" paramsMap.level !=null and paramsMap.level !='' ">
          AND ic.comment_level = #{paramsMap.level}
        </if>
  </select>

    <select id="searchItems" parameterType="Map" resultType="com.imooc.pojo.vo.SearchItemsVO">
            SELECT
                i.id AS itemId,
                i.item_name AS itemName,
                i.sell_counts AS sellCounts,
                ii.url AS imgUrl,
                tempSpec.priceDiscount AS price
            FROM
                items i
                LEFT JOIN items_img ii ON i.id = ii.item_id
                LEFT JOIN ( SELECT item_id, MIN( price_discount ) AS priceDiscount FROM items_spec GROUP BY item_id ) tempSpec
                ON i.id = tempSpec.item_id
            WHERE
                ii.is_main = 1
                <if test=" paramsMap.keywords !=null and paramsMap.keywords !='' ">
                    AND i.item_name like  '%${paramsMap.keywords}%'
                </if>
                    order by
               <choose>
                   <when test=" paramsMap.sort == &quot;c &quot;  ">
                      i.sell_counts desc
                   </when>
                   <when test=" paramsMap.sort ==  &quot;p &quot;  ">
                       tempSpec.priceDiscount desc
                   </when>
                   <otherwise>
                       i.item_name asc
                   </otherwise>
               </choose>
    </select>

    <select id="searchItemsByThirdCat" parameterType="Map" resultType="com.imooc.pojo.vo.SearchItemsVO">
        SELECT
        i.id AS itemId,
        i.item_name AS itemName,
        i.sell_counts AS sellCounts,
        ii.url AS imgUrl,
        tempSpec.priceDiscount AS price
        FROM
        items i
        LEFT JOIN items_img ii ON i.id = ii.item_id
        LEFT JOIN ( SELECT item_id, MIN( price_discount ) AS priceDiscount FROM items_spec GROUP BY item_id ) tempSpec
        ON i.id = tempSpec.item_id
        WHERE
        ii.is_main = 1
          AND i.cat_id = #{paramsMap.catId}
          order by
        <choose>
            <when test=" paramsMap.sort == &quot;c &quot;  ">
                i.sell_counts desc
            </when>
            <when test=" paramsMap.sort ==  &quot;p &quot;  ">
                 tempSpec.priceDiscount desc
            </when>
            <otherwise>
                i.item_name asc
            </otherwise>
        </choose>
    </select>
    <!-- k:默認,代表默認排序,根據name -->
    <!-- c:根據銷量排序 -->
    <!-- p:根據價格排序 -->

    <select id="queryItemsBySpecIds" parameterType="List" resultType="com.imooc.pojo.vo.ShopcartVO">
        SELECT
            i.id AS itemId,
            ii.url AS itemImgUrl,
            i.item_name AS itemName,
            sp.id AS specId,
            sp.`name` AS specName,
            sp.price_discount AS priceDiscount,
            sp.price_normal AS priceNormal
        FROM
            items_spec sp
            LEFT JOIN items i ON i.id = sp.item_id
            LEFT JOIN items_img ii ON i.id = ii.item_id
        WHERE
            ii.is_main = 1
            AND sp.id IN
            <foreach collection="paramsList" index="index" item="specId" open="(" separator="," close=")">
                 #{specId}
            </foreach>

    </select>

</mapper>
View Code

 

package com.imooc.pojo.vo;

public class ShopcartVO {

    private  String itemId;
    private  String itemImgUrl;
    private  String itemName;
    private  String specId;
    private  String specName;
    private  String priceDiscount;
    private  String priceNormal;

    public String getItemId() {
        return itemId;
    }

    public void setItemId(String itemId) {
        this.itemId = itemId;
    }

    public String getItemImgUrl() {
        return itemImgUrl;
    }

    public void setItemImgUrl(String itemImgUrl) {
        this.itemImgUrl = itemImgUrl;
    }

    public String getItemName() {
        return itemName;
    }

    public void setItemName(String itemName) {
        this.itemName = itemName;
    }

    public String getSpecId() {
        return specId;
    }

    public void setSpecId(String specId) {
        this.specId = specId;
    }

    public String getSpecName() {
        return specName;
    }

    public void setSpecName(String specName) {
        this.specName = specName;
    }

    public String getPriceDiscount() {
        return priceDiscount;
    }

    public void setPriceDiscount(String priceDiscount) {
        this.priceDiscount = priceDiscount;
    }

    public String getPriceNormal() {
        return priceNormal;
    }

    public void setPriceNormal(String priceNormal) {
        this.priceNormal = priceNormal;
    }

}
View Code

 (4)定義接口方法

      注意參數名稱和xml內保持一致

         

       

package com.imooc.mapper;

import com.imooc.pojo.vo.ItemCommentVO;
import com.imooc.pojo.vo.SearchItemsVO;
import com.imooc.pojo.vo.ShopcartVO;
import org.apache.ibatis.annotations.Param;


import java.util.List;
import java.util.Map;

public interface ItemsMapperCustom  {

    public List<ItemCommentVO> queryItemComments (@Param("paramsMap") Map<String, Object> map);

    public List<SearchItemsVO> searchItems(@Param("paramsMap") Map<String, Object> map);

    public List<SearchItemsVO> searchItemsByThirdCat(@Param("paramsMap") Map<String, Object> map);

    public List<ShopcartVO> queryItemsBySpecIds(@Param("paramsList") List<String> specIds);


}
View Code

   (5)service層

            

          

package com.imooc.service;


import com.imooc.pojo.Items;
import com.imooc.pojo.ItemsImg;
import com.imooc.pojo.ItemsParam;
import com.imooc.pojo.ItemsSpec;
import com.imooc.pojo.vo.CommentLevelCountsVO;
import com.imooc.pojo.vo.ItemCommentVO;
import com.imooc.pojo.vo.SearchItemsVO;
import com.imooc.pojo.vo.ShopcartVO;
import com.imooc.utils.PagedGridResult;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

public interface ItemService {

    /**
     * 根據商品ID查詢詳情
     * @param itemId
     * @return
     */
    public Items queryItemById(String itemId);

    /**
     * 根據商品ID查詢圖片列表
     * @param itemId
     * @return
     */
    public List<ItemsImg> queryItemImgList(String itemId);

    /**
     * 根據商品ID查詢商品規格列表
     * @param itemId
     * @return
     */
    public List<ItemsSpec> queryItemSpecList(String itemId);

    /**
     * 根據商品ID查詢商品參數
     * @param itemId
     * @return
     */
    public ItemsParam queryItemParam(String itemId);

    /**
     * 根據商品id查詢商品的評價等級數量
     * @param itemId
     */
    public CommentLevelCountsVO queryItemCommentCounts(String itemId);

    /**
     * 根據商品id查詢商品評價(分頁)
     * @param itemId
     * @param leve
     * @return
     */
    public PagedGridResult queryPagedComments (String itemId, Integer leve,Integer page,Integer pageSize);

    /**
     * 搜索商品列表
     * @param keyWords
     * @param sort
     * @param page
     * @param pageSize
     * @return
     */
    public PagedGridResult searchItems(String keyWords,String sort,Integer page,Integer pageSize);

    /**
     * 三級分類商品列表
     * @param catId
     * @param sort
     * @param page
     * @param pageSize
     * @return
     */
    public PagedGridResult searchItemsByThirdCat(Integer catId,String sort,Integer page,Integer pageSize);

    /**
     * 根據規格ids查詢最新的購物車中商品數據(用於刷新渲染購物車中的商品數據)
     * @param specIds
     * @return
     */
    public List<ShopcartVO> queryItemsBySpecIds(String specIds);

}
View Code

 

            

       

package com.imooc.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.imooc.enums.CommentLevel;
import com.imooc.mapper.*;
import com.imooc.pojo.*;
import com.imooc.pojo.vo.CommentLevelCountsVO;
import com.imooc.pojo.vo.ItemCommentVO;
import com.imooc.pojo.vo.SearchItemsVO;
import com.imooc.pojo.vo.ShopcartVO;
import com.imooc.service.ItemService;
import com.imooc.utils.DesensitizationUtil;
import com.imooc.utils.PagedGridResult;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.*;

@Service
public class ItemServiceImpl implements ItemService {
    @Autowired
    ItemsMapper itemsMapper;

    @Autowired
    ItemsImgMapper itemsImgMapper;

    @Autowired
    ItemsSpecMapper itemsSpecMapper;

    @Autowired
    ItemsParamMapper itemsParamMapper;

    @Autowired
    ItemsCommentsMapper itemsCommentsCommentsMapper;

    @Autowired
    ItemsMapperCustom itemsMapperCustom;

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public Items queryItemById(String itemId) {
        return itemsMapper.selectByPrimaryKey(itemId);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public List<ItemsImg> queryItemImgList(String itemId) {
        Example itemsImgExp = new Example(ItemsImg.class);
        Example.Criteria criteria =itemsImgExp.createCriteria();
        criteria.andEqualTo("itemId",itemId);
        return itemsImgMapper.selectByExample(itemsImgExp);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public List<ItemsSpec> queryItemSpecList(String itemId) {
        Example itemsSpecExp = new Example(ItemsSpec.class);
        Example.Criteria criteria =itemsSpecExp.createCriteria();
        criteria.andEqualTo("itemId",itemId);
        return itemsSpecMapper.selectByExample(itemsSpecExp);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public ItemsParam queryItemParam(String itemId) {
        Example itemsParamExp = new Example(ItemsParam.class);
        Example.Criteria criteria =itemsParamExp.createCriteria();
        criteria.andEqualTo("itemId",itemId);
        return itemsParamMapper.selectOneByExample(itemsParamExp);
    }



    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public CommentLevelCountsVO queryItemCommentCounts(String itemId) {

       //Integer totalCounts=getCommentCounts(itemId);
        Integer goodCounts=getCommentCounts(itemId, CommentLevel.Good.type);
        Integer normalCounts=getCommentCounts(itemId, CommentLevel.NORMAL.type);
        Integer badCounts=getCommentCounts(itemId, CommentLevel.BAD.type);
        Integer totalCounts=goodCounts+normalCounts+badCounts;

        CommentLevelCountsVO commentLevelCountsVO=new CommentLevelCountsVO();
        commentLevelCountsVO.setTotalCounts(totalCounts);
        commentLevelCountsVO.setGoodCounts(goodCounts);
        commentLevelCountsVO.setNormalCounts(normalCounts);
        commentLevelCountsVO.setBadCounts(badCounts);
        return commentLevelCountsVO;
    }

    @Transactional(propagation = Propagation.SUPPORTS)
     Integer getCommentCounts(String itemId,Integer level){

        ItemsComments confdition =new ItemsComments();
        confdition.setItemId(itemId);
        if (level != null) {
            confdition.setCommentLevel(level);
        }

      return   itemsCommentsCommentsMapper.selectCount(confdition);

    }
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public PagedGridResult queryPagedComments(String itemId,
                                                  Integer level,
                                                  Integer page,
                                                  Integer pageSzie) {
        Map<String,Object> map =new HashMap<>();
        map.put("itemId",itemId);
        map.put("level",level);
        /**
         * page:第幾頁
         * pageSize:每頁顯示多少條
         */
        PageHelper.startPage(page,pageSzie);
        List<ItemCommentVO> list=itemsMapperCustom.queryItemComments(map);
        for (ItemCommentVO vo : list
             ) {
              vo.setNickName(DesensitizationUtil.commonDisplay(vo.getNickName()));
        }
        return setterPagedGrid(list,page);

    }

    private PagedGridResult setterPagedGrid(List<?> list,Integer page){

        PageInfo<?> pageList = new PageInfo<>(list);
        PagedGridResult grid = new PagedGridResult();
        grid.setPage(page);
        grid.setRows(list);
        grid.setTotal(pageList.getPages());
        grid.setRecords(pageList.getTotal());
        return grid;

    }
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public PagedGridResult searchItems(String keywords, String sort, Integer page, Integer pageSize) {
        Map<String,Object> map =new HashMap<>();
        map.put("keywords",keywords);
        map.put("sort",sort);
        /**
         * page:第幾頁
         * pageSize:每頁顯示多少條
         */
        PageHelper.startPage(page,pageSize);
        List<SearchItemsVO> list=itemsMapperCustom.searchItems(map);
        return setterPagedGrid(list,page);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public PagedGridResult searchItemsByThirdCat(Integer catId, String sort, Integer page, Integer pageSize) {
        Map<String,Object> map =new HashMap<>();
        map.put("catId",catId);
        map.put("sort",sort);
        /**
         * page:第幾頁
         * pageSize:每頁顯示多少條
         */
        PageHelper.startPage(page,pageSize);
        List<SearchItemsVO> list=itemsMapperCustom.searchItemsByThirdCat(map);
        return setterPagedGrid(list,page);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public List<ShopcartVO> queryItemsBySpecIds(String specIds) {

        String ids[] =specIds.split(",");
        List<String> specIdList = new ArrayList<>();
        Collections.addAll(specIdList,ids);
        return itemsMapperCustom.queryItemsBySpecIds(specIdList);

    }
}
View Code

 (6)Api子模塊 (controller層)

     

         

package com.imooc.controller;

import com.imooc.enums.YesOrNo;
import com.imooc.pojo.*;
import com.imooc.pojo.vo.*;
import com.imooc.service.CarouselService;
import com.imooc.service.CategoryService;
import com.imooc.service.ItemService;
import com.imooc.utils.IMOOCJSONResult;
import com.imooc.utils.PagedGridResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@Api(value = "商品接口",tags = "商品信息展示的相關接口")
@RestController
@RequestMapping("item")
public class ItemController {

    @Autowired
     private ItemService itemService;

    @ApiOperation(value="查詢商品詳情",notes = "查詢商品詳情",httpMethod = "GET")
    @GetMapping("/info/{itemId}")
    public IMOOCJSONResult info(
            @ApiParam(name = "itemId",value = "商品ID",required = true)
            @PathVariable() String itemId) {
         if (StringUtils.isBlank(itemId)) {

             return IMOOCJSONResult.errorMsg("");

         }


        Items item = itemService.queryItemById(itemId);
        List<ItemsImg> itemImgList=itemService.queryItemImgList(itemId);
        List<ItemsSpec> itemSpecList=itemService.queryItemSpecList(itemId);
        ItemsParam itemParam=itemService.queryItemParam(itemId);
        ItemInfoVO itemInfoVO=new ItemInfoVO();
        itemInfoVO.setItem(item);
        itemInfoVO.setItemImgList(itemImgList);
        itemInfoVO.setItemSpecList(itemSpecList);
        itemInfoVO.setItemParam(itemParam);

        return IMOOCJSONResult.ok(itemInfoVO);
    }


    @ApiOperation(value="查詢商品評價分頁",notes = "查詢商品評價分頁",httpMethod = "GET")
    @GetMapping("/comments")
    public IMOOCJSONResult comments(
            @ApiParam(name = "itemId",value = "商品ID",required = true)
            @RequestParam() String itemId,
            @ApiParam(name = "level",value = "評價等級",required = false)
            @RequestParam() Integer level,
            @ApiParam(name = "page",value = "查詢下一頁的第幾頁",required = false)
            @RequestParam() Integer page,
            @ApiParam(name = "pageSize",value = "分頁每一頁顯示的條數",required = false)
            @RequestParam() Integer pageSize
            ) {
        if (StringUtils.isBlank(itemId)) {

            return IMOOCJSONResult.errorMsg("");
        }
        if(page==null) {
            page=1;
        }
        if(pageSize==null) {
            pageSize=10;
        }


        PagedGridResult grid = itemService.queryPagedComments(itemId,level,page,pageSize);
        return IMOOCJSONResult.ok(grid);
    }

    @ApiOperation(value="查詢商品評價等級",notes = "查詢商品評價等級",httpMethod = "GET")
    @GetMapping("/commentLevel")
    public IMOOCJSONResult commentLevel(
            @ApiParam(name = "itemId",value = "商品ID",required = true)
            @RequestParam() String itemId) {
        if (StringUtils.isBlank(itemId)) {

            return IMOOCJSONResult.errorMsg("");

        }
        CommentLevelCountsVO countsVO = itemService.queryItemCommentCounts(itemId);
        return IMOOCJSONResult.ok(countsVO);
    }

    @ApiOperation(value="搜索商品列表分頁",notes = "搜索商品列表分頁",httpMethod = "GET")
    @GetMapping("/search")
    public IMOOCJSONResult search(
            @ApiParam(name = "keywords",value = "關鍵字",required = true)
            @RequestParam() String keywords,
            @ApiParam(name = "sort",value = "排序",required = false)
            @RequestParam() String sort,
            @ApiParam(name = "page",value = "查詢下一頁的第幾頁",required = false)
            @RequestParam() Integer page,
            @ApiParam(name = "pageSize",value = "分頁每一頁顯示的條數",required = false)
            @RequestParam() Integer pageSize
    ) {
        if (StringUtils.isBlank(keywords)) {

            return IMOOCJSONResult.errorMsg("");
        }
        if (page == null) {
            page = 1;
        }

        if(pageSize==null) {
            pageSize=20;
        }

        PagedGridResult grid = itemService.searchItems(keywords,sort,page,pageSize);
        return IMOOCJSONResult.ok(grid);
    }

    @ApiOperation(value="通過三級分類Id搜索商品列表分頁",notes = "通過三級分類Id搜索商品列表分頁",httpMethod = "GET")
    @GetMapping("/catItems")
    public IMOOCJSONResult catItems(
            @ApiParam(name = "catId",value = "三級分類id",required = true)
            @RequestParam() Integer catId,
            @ApiParam(name = "sort",value = "排序",required = false)
            @RequestParam() String sort,
            @ApiParam(name = "page",value = "查詢下一頁的第幾頁",required = false)
            @RequestParam() Integer page,
            @ApiParam(name = "pageSize",value = "分頁每一頁顯示的條數",required = false)
            @RequestParam() Integer pageSize
    ) {
        if (catId==null) {

            return IMOOCJSONResult.errorMsg("");
        }
        if (page == null) {
            page = 1;
        }

        if(pageSize==null) {
            pageSize=20;
        }

        PagedGridResult grid = itemService.searchItemsByThirdCat(catId,sort,page,pageSize);
        return IMOOCJSONResult.ok(grid);
    }

    //用於用戶長時間未登錄網站,刷新購物車中的數據(主要是商品價格),類似京東淘寶
    @ApiOperation(value="根據規格ids查詢最新的購物車中商品數據",notes = "根據規格ids查詢最新的購物車中商品數據",httpMethod = "GET")
    @GetMapping("/refresh")
    public IMOOCJSONResult refresh(
            @ApiParam(name = "itemSpecIds",value = "拼接的規格ids",required = true,example = "1001,1002,1103")
            @RequestParam() String itemSpecIds

    ) {
        if(StringUtils.isBlank(itemSpecIds)) {
            return IMOOCJSONResult.ok();
        }
        List<ShopcartVO> list=itemService.queryItemsBySpecIds(itemSpecIds);
        return IMOOCJSONResult.ok(list);
    }
}
View Code

     7、前端代碼

          

          

四、刪除商品

  購物車內商品的刪除,考慮兩種情況,一個是用戶未登陸,一個是用戶已登錄。

  如果未登陸直接在前端刪除,如果用戶已登錄,那么就要拿着這條數據到后端的購物車里面刪除。這樣也是保證我們前后端數據的同步。

      1、前端代碼分析

          刪除的方法傳入的是商品的規格id。購物車里面,商品是以規格作為單位的。

        

 刪除前端對象中的這個規格的商品

 新的list重新放到cookie里面

  

 

  2、用戶登陸的情況,把商品的規格id傳遞到后端

3.后端接口

  

  

package com.imooc.controller;

import com.imooc.pojo.bo.ShopcartBO;
import com.imooc.utils.IMOOCJSONResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;


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


@Api(value = "購物車接口controller",tags = {"購物車接口相關的api"})
@RequestMapping("shopcart")
@RestController
public class ShopcartController {

    @ApiOperation(value = "添加商品到購物車",notes = "添加商品到購物車",httpMethod = "POST")
    @PostMapping("/add")
    public IMOOCJSONResult add(
            @RequestParam String userId,
            @RequestBody ShopcartBO shopcartBO,
            HttpServletRequest request,
            HttpServletResponse response
            ) {
           if (StringUtils.isBlank(userId)) {
             return   IMOOCJSONResult.errorMsg("");
           }
        System.out.println(shopcartBO);
           //TODO 前端用戶在登錄的情況下,添加商品到購物車,會同時在后端同步購物車到redis緩存

        return IMOOCJSONResult.ok();

    }

    @ApiOperation(value = "從購物車中刪除商品",notes = "從購物車中刪除商品",httpMethod = "POST")
    @PostMapping("/del")
    public IMOOCJSONResult del(
            @RequestParam String userId,
            @RequestParam String itemSpecId,
            HttpServletRequest request,
            HttpServletResponse response
    ) {
        if (StringUtils.isBlank(userId) || StringUtils.isBlank(itemSpecId)) {
            return   IMOOCJSONResult.errorMsg("");
        }

        //TODO 用戶在頁面刪除購物車中的商品數據,如果此時用戶已經登錄,則需要同步刪除后端購物車中的數據

        return IMOOCJSONResult.ok();

    }
}
View Code

 五、提交購物車至結算頁

  

判斷用戶是否登陸

  

支付頁面的聲明周期函數

 

最終的商品數據


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM