宜立方商城—— 購物車增加、刪除、修改數量、刪除選中商品和清空購物車的實現

1.  購物車的實現

1.1. 功能分析

1、購物車是一個獨立的表現層工程。

2、添加購物車不要求登錄。可以指定購買商品的數量。

3、展示購物車列表頁面

4、修改購物車商品數量

5、刪除購物車商品

模塊劃分結構

1.1. 添加購物車

1.1.1.    功能分析

在不登陸的情況下也可以添加購物車。把購物車信息寫入cookie。

優點:

1、不佔用服務端存儲空間

2、用戶體驗好。

3、代碼實現簡單。

缺點:

1、cookie中保存的容量有限。最大4k

2、把購物車信息保存在cookie中,更換設備購物車信息不能同步。

請求的url:/cart/add/{itemId}

參數:

1)商品id: Long itemId
2)商品數量: int num

業務邏輯:

1、從cookie中查詢商品列表。

2、判斷商品在商品列表中是否存在。

3、如果存在,商品數量相加。

4、不存在,根據商品id查詢商品信息。

5、把商品添加到購車列表。

6、把購車商品列表寫入cookie。

 

返回值:邏輯視圖

Controller

/**
 * 購物車Controller
 * @Auther: jun
 * @Date: 2018/5/31 0031 19:44
 * @Description:
 */
@Controller
public class CartController {
    @Autowired
    private ItemService itemService;
    @Autowired
    private CartService cartService;
    @Value("${COOKIE_CART_EXIPERE}")
    private Integer COOKIE_CART_EXIPERE;
    /**
     *添加購物車商品
     * @auther: jun
     * @date: 2018/5/31 0031 22:16
     * @param itemId,num,request,response
     * @return: java.lang.String
     * @Description:
     */
    @RequestMapping("/cart/add/{itemId}")
    public String addCart(@PathVariable Long itemId, @RequestParam(defaultValue = "1") Integer num,
                          HttpServletRequest request, HttpServletResponse response){
        //判斷用戶是否登錄
        //從request中獲取到用戶信息
        TbUser user = (TbUser) request.getAttribute("user");
        //判斷是否有值有就是登陸狀態把購物車寫入redis中
        if (user !=null){
            //保存到服務端(redis)
            cartService.addCart(user.getId(),itemId,num);
            //返回邏輯視圖
            return "cartSuccess";
        }
        //從cookie中獲取到購物車列表
        List<TbItem> cartList = getCartListFromCookie(request);
        //用於判斷購物車中是否有添加的商品信息
        boolean flag=false;
        //遍歷購物車商品列表
        for (TbItem item:cartList) {
            //判斷添加的商品是否在購物冊列表中使用商品id判斷
            if (itemId.equals(item.getId())){
                //如果在flag爲true
                flag=true;
                //並且購物車中商品數量加上添加商品的的數量
                item.setNum(item.getNum()+num);
                //跳出循環
                break;
            }
        }
        //如果不存在
        if(!flag){
            //根據商品id查詢得到一個TbItem對象
            TbItem item = itemService.getItemById(itemId);
            //設置商品數量
            item.setNum(num);
            //取一張圖片
            String image = item.getImage();
            if (StringUtils.isNoneBlank(image)){
              //設置第一張圖片
                item.setImage(image.split(",")[0]);
            }
            //添加商品到購物車商品列表中
            cartList.add(item);
        }
        //寫入cookie中需要數據需要轉換成json數據還有過期時間1個小時,還要編碼實現
        CookieUtils.setCookie(request,response,"cart",JsonUtils.objectToJson(cartList),COOKIE_CART_EXIPERE,true);
        //返回邏輯視圖頁面
        return "cartSuccess";
    }
/**
 *從cookie中取購物車列表的處理
 * @auther: jun
 * @date: 2018/5/31 0031 19:47
 * @param request
 * @return: java.util.List<com.e3mall.pojo.TbItem>
 * @Description: 
 */
private List<TbItem> getCartListFromCookie(HttpServletRequest request){
    //從cookie中取出數據時需要轉碼
    String json = CookieUtils.getCookieValue(request, "cart", true);
    //判斷json是否爲空
    if (StringUtils.isBlank(json)){
        //避免空值
        return new ArrayList<>();
    }
    //返回List的商品列表
    return JsonUtils.jsonToList(json,TbItem.class);
}
 

Service層

配置文件resource.properties


/**
 * 購物車Service
 * @Auther: jun
 * @Date: 2018/6/1 0001 15:23
 * @Description:
 */
@Service
public class CartServiceImpl implements CartService {
    @Autowired
    private JedisClient jedisClient;
    @Autowired
    private TbItemMapper itemMapper;
    @Value("${REDIS_CART_PRE}")
    private String REDIS_CART_PRE;

    @Override
    public E3Result addCart(Long userId, Long itemId,Integer num) {
        //向redis中添加購物車
        //數據類型:hash類型 key:用戶id filed:商品id value :商品信息
        //判斷商品是否存在
        Boolean hexists = jedisClient.hexists(REDIS_CART_PRE + ":" + userId, itemId.toString());
        if (hexists){
            //存在獲取到redis中的存在的商品值
            String json = jedisClient.hget(REDIS_CART_PRE + ":" + userId, itemId.toString());
            //把json轉換成pojo對象
            TbItem item = JsonUtils.jsonToPojo(json, TbItem.class);
            //數量相加
            item.setNum(item.getNum()+num);
            //重新寫入redis中
            jedisClient.hset(REDIS_CART_PRE + ":" + userId,itemId.toString(),JsonUtils.objectToJson(item));
            //退出返回結果
            return E3Result.ok();
        }
        //不存在就是要查詢數據庫並且存入redis中
        //根據商品id查詢商品信息
        TbItem item = itemMapper.selectByPrimaryKey(itemId);
        //設置數量
        item.setNum(num);
        //取一張圖片存入item中
        String image = item.getImage();
        if (StringUtils.isNoneBlank(image)){
            item.setImage(image.split(",")[0]);
        }
        jedisClient.hset(REDIS_CART_PRE + ":" + userId,itemId.toString(),JsonUtils.objectToJson(item));
        return E3Result.ok();
    }

applicationContent-service.xml發佈服務

<!-- 使用dubbo發佈服務 -->
<!-- 提供方應用信息,用於計算依賴關係 -->
<dubbo:application name="e3-sso" />
<dubbo:registry protocol="zookeeper" address="192.168.25.128:2181" />
<!-- 用dubbo協議在20880端口暴露服務 -->
<dubbo:protocol name="dubbo" port="20884" />
<!-- 聲明需要暴露的服務接口 -->
<!--購物車服務-->
<dubbo:service interface="com.e3mall.cart.service.CartService" ref="cartServiceImpl" timeout="600000"/>

springmvc.xml 調用服務

<!-- 引用dubbo服務 -->
<dubbo:application name="e3-cart-web"/>
<dubbo:registry protocol="zookeeper" address="192.168.25.128:2181"/>
<!--商品服務-->
<dubbo:reference interface="com.e3mall.service.ItemService" id="itemService" />
<!--sso服務-->
<dubbo:reference interface="com.e3mall.sso.service.TokenService" id="tokenService" />
<dobbo:reference interface="com.e3mall.cart.service.CartService" id="cartService"/>

配置用戶攔截器判斷用戶是登錄和未登錄狀態

/**
 * 用戶登錄攔截器實現
 *
 * @Auther: jun
 * @Date: 2018/6/1 0001 14:38
 * @Description:
 */
public class LoginInterceptor implements HandlerInterceptor {
    @Autowired
    private TokenService tokenService;
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {
        //前處理,執行handler之前執行此方法
        // 返回true 放行 false 攔截
        //1.從cookie中取出token
        String token = CookieUtils.getCookieValue(httpServletRequest, "token");
        //2.如果沒有token,未登錄狀態,直接放行
        if (StringUtils.isBlank(token)){
            //放行
            return true;
        }
        //3.取到token,炫耀調用sso系統的服務,根據token去用戶信息
        E3Result result = tokenService.getUserByToker(token);
        //4.沒有取到用戶信息,登錄過期,直接放行
        //判斷狀態爲200 登錄成功
        if (result.getStatus()!=200){
           return true;
        }
        //在token中取用戶信息
        //5.取到用戶信息,登錄狀態
        TbUser user = (TbUser) result.getData();
        //6.把用戶信息放到request中,只需要在Controller中判斷request中是否包含user信息
        httpServletRequest.setAttribute("user",user);
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler, ModelAndView modelAndView) throws Exception {
    //handler執行之後,返回ModelAndView之前
    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler, Exception e) throws Exception {
        //完成處理之後,返回ModelAndView之後
        //可以在此處理異常
    }

在springmvc.xml攔截器配置

<mvc:interceptors>
    <mvc:interceptor>
        <!--攔截所有的url-->
        <mvc:mapping path="/**"/>
        <!--配置攔截器的實現類-->
        <bean class="com.e3mall.cart.interceptor.LoginInterceptor"/>
    </mvc:interceptor>
</mvc:interceptors>

1.1. 展示購物車商品列表

請求的url:/cart/cart

參數:無

返回值:邏輯視圖

業務邏輯:

需要考慮登錄用戶redis中的購物車數據和cookie中的數據和並

沒有登錄就展示cookie中的數據

1、從cookie中取商品列表。

2、把商品列表傳遞給頁面。

    引用服務
/**
 *購物車展示
 * @auther: jun
 * @date: 2018/5/31 0031 20:38
 * @param request
 * @return: java.lang.String
 * @Description:
 */
@RequestMapping("/cart/cart")
public  String showCartList(HttpServletRequest request,HttpServletResponse response){
    //從cookie中取購物車列表
    List<TbItem> cartList = getCartListFromCookie(request);
    //判斷用戶是否爲登錄狀態
    TbUser user = (TbUser) request.getAttribute("user");
    //如果是登錄狀態
    if (user!=null){
        //如果不爲空,把cookie購物車和redis中的購物車商品信息合併
        cartService.mergeCart(cartList, user.getId());
        //把cookie中的購物車商品刪除
        CookieUtils.deleteCookie(request,response,"cart");
        //從redis取購物車列表信息
        cartList = cartService.getCartList(user.getId());
    }

    //未登錄狀態
   // List<TbItem> cartList = cartList;
    //把列表轉遞給頁面
    request.setAttribute("cartList",cartList);
    //返回邏輯視圖
    return "cart";
}

Service

合併數據的實現方法

@Override
public E3Result mergeCart(List<TbItem> itemList, Long userId) {
    //遍歷商品列表
    //把商品列表添加到購物車中
    //判斷購物車中是否有該商品
    //如果有就商品數量相加
    //沒有就添加新的商品信息
    for (TbItem item : itemList) {
        //調用添加購物車方法實現
        addCart(userId,item.getId(),item.getNum());
    }
    //返回成功
    return E3Result.ok();
}

展示購物車數據

@Override
public List<TbItem> getCartList(Long userId) {
    //根據用戶id查詢購物車商品列表(redis 中的鍵找值)
    List<String> jsonList = jedisClient.hvals(REDIS_CART_PRE + ":" + userId);
    //創建一個商品列表信息
    List<TbItem> itemList=new ArrayList<>();
    for (String string : jsonList) {
        //獲取到json中一個數據並轉換數據類型成pojo對象
        TbItem item = JsonUtils.jsonToPojo(string, TbItem.class);
        //添加到列表
        itemList.add(item);
    }
    //返回列表
    return itemList;
}

發佈服務

1.1. 修改購物車商品數量

1.1.1.    功能分析

1、在頁面中可以修改商品數量

2、重新計算小計和總計。

3、修改需要寫入cookie。

4、每次修改都需要向服務端發送一個ajax請求,在服務端修改cookie中的商品數量。

請求的url:/cart/update/num/{itemId}/{num}

參數:long itemId、int num

業務邏輯:

1、接收兩個參數

2、從cookie中取商品列表

3、遍歷商品列表找到對應商品

4、更新商品數量

5、把商品列表寫入cookie。

6、響應e3Result。Json數據。

返回值:

 e3Result。Json數據

Controller

引用服務

/**
 *修改商品數據功能
 * @auther: jun
 * @date: 2018/5/31 0031 22:16
 * @param itemId,num,request,response
 * @return: com.e3mall.common.utils.E3Result
 * @Description:
 */
@RequestMapping("/cart/update/num/{itemId}/{num}")
@ResponseBody
public E3Result updateCartNum(@PathVariable Long itemId,@PathVariable Integer num,
                              HttpServletRequest request,HttpServletResponse response){
    //獲取登錄信息
    TbUser user = (TbUser) request.getAttribute("user");
    //判斷登錄狀態
    if (user!=null){
        //調用服務更新
        cartService.updateCartNum(user.getId(), itemId, num);
        return E3Result.ok();
    }
    //從cookie中獲取到商品列表
    List<TbItem> cartList= getCartListFromCookie(request);
    //遍歷列表
    for (TbItem item:cartList){
        //根據id修改商品列表中的數量信息
        if (itemId==item.getId().longValue()){
            item.setNum(num);
        }
        //退出
        break;
    }
    //把購物車寫回cookie
    CookieUtils.setCookie(request,response,"cart",JsonUtils.objectToJson(cartList),COOKIE_CART_EXIPERE,true);
    //返回結果
    return E3Result.ok();
}

Service

@Override
public E3Result updateCartNum(Long userId, Long itemId, Integer num) {
    //獲取到購物車中商品信息
    String json = jedisClient.hget(REDIS_CART_PRE + ":" + userId, itemId.toString());
        //轉換json成pojo對象
        TbItem item = JsonUtils.jsonToPojo(json, TbItem.class);
        //寫入數量
        item.setNum(num);
        //回寫到redis中
        jedisClient.hset(REDIS_CART_PRE + ":" + userId,itemId.toString(),JsonUtils.objectToJson(item));
    //返回結果
    return E3Result.ok();
}

發佈服務

2、重新計算小計和總計。jsp頁面修改

1.修改cart.jsp


cart.js

加減方法中添加的

CART.refreshTotal(_thisInput.val(),_thisInput.attr("itemId"));



1.1. 刪除購物車商品

1.1.1.    功能分析

請求的url:/cart/delete/{itemId}

參數:商品id

返回值:展示購物車列表頁面。Url需要做redirect跳轉。

業務邏輯:

1、從url中取商品id

2、從cookie中取購物車商品列表

3、遍歷列表找到對應的商品

4、刪除商品。

5、把商品列表寫入cookie。

6、返回邏輯視圖:在邏輯視圖中做redirect跳轉。

Controller

引用服務

/**
 *刪除購物車商品
 * @auther: jun
 * @date: 2018/6/1 0001 17:18
 * @param itemId,request,response
 * @return: java.lang.String
 * @Description:
 */
@RequestMapping("/cart/delete/{itemId}")
public  String deleteCartItem(@PathVariable Long itemId,
                              HttpServletRequest request,HttpServletResponse response){
    //獲取登錄信息
    TbUser user = (TbUser) request.getAttribute("user");
    //判斷登錄狀態
    if (user!=null){
        //調用服務更新
        cartService.deleteCartItem(user.getId(), itemId);
        //返回邏輯視圖
        return "redirect:/cart/cart.html";
    }
    //從cookie中獲取商品列表
    List<TbItem> cartList = getCartListFromCookie(request);
    //遍歷列表
    for (TbItem item:cartList){
        //根據id刪除指定商品列表中的數據
        if (itemId==item.getId().longValue()){
            //移除cookie中的商品信息
            cartList.remove(item);
        }
        //退出
        break;
    }
Service

@Override
public E3Result deleteCartItem(Long userId, Long itemId) {
    //刪除指定id的商品
    jedisClient.hdel(REDIS_CART_PRE + ":" + userId,itemId.toString());
    //返回結果
    return E3Result.ok();
}

發佈服務

清空購物車

需要修改一下jsp並且還要寫一段js代碼


Controller代碼

/**
 *清空購物車
 * @auther: jun
 * @date: 2018/6/4 0004 13:10
 * @param request
 * @param response
 * @return: java.lang.String
 * @Description:
 */
@RequestMapping("/cart/clearCart")
public String clearCart(HttpServletRequest request, HttpServletResponse response) throws IOException {
    //獲取用戶信息
    TbUser user = (TbUser) request.getAttribute ("user");
    //是否登錄狀態
    if (user != null) {
        //調用服務清除購物車合併後的數據
        cartService.clearCartItem (user.getId ());
        return "redirect:/cart/cart.html";
    }
    //cookie清除
   CookieUtils.deleteCookie (request, response, "cart");
    return "redirect:/cart/cart.html";
}

調用服務

@Override
public E3Result clearCartItem(Long userId) {
    //刪除購物車信息
    jedisClient.del (REDIS_CART_PRE+":"+userId);
    return E3Result.ok ();
}

發佈服務

刪除選中的商品的功能實現

jsp修改頁面value


js代碼段


Controller

這裏我們考慮了登錄和未登錄狀態問題所以我們操作了cookie數據和redis中的數據

/**
 * 批量刪除購物車中的商品
 *
 * @param ids
 * @param request
 * @param response
 * @auther: jun
 * @date: 2018/6/4 0004 10:48
 * @return: com.e3mall.common.utils.E3Result
 * @Description:
 */
@RequestMapping(value = "/cart/cartDelMore")
@ResponseBody
public E3Result cartDelMore(String[] ids,
                            HttpServletRequest request, HttpServletResponse response) {
    //判斷是否是登錄狀態
    TbUser user = (TbUser) request.getAttribute ("user");
    if (user != null) {
        //調用服務執行批量刪除商品
        cartService.cartDelMore (user.getId (), ids);
    }
    //未登錄狀態
    //從cookie中獲取商品列表
    List<TbItem> cartList = getCartListFromCookie (request);
    //遍歷參數數組
    for (String id : ids) {
        //遍歷商品列表
        for (TbItem item : cartList) {
            //判斷
            if (Long.parseLong (id) ==item.getId ().longValue () ) {
                //移除
                cartList.remove (item);
                //退出當前商品列表集合
                break;
            }
        }
    }
    //重新寫入列表到cookie
    CookieUtils.setCookie (request, response, "cart", JsonUtils.objectToJson (cartList), COOKIE_CART_EXIPERE, true);
    return E3Result.ok ();
}

Service

@Override
public E3Result cartDelMore(Long userId, String[] ids) {
    for (String itemId:ids){
        //刪除指定id的商品
        jedisClient.hdel(REDIS_CART_PRE + ":" + userId,itemId);
    }
    return E3Result.ok ();
}

1.1. 小結

使用cookie實現購物車:

優點:

1、實現簡單

2、不需要佔用服務端存儲空間。

缺點:

1、存儲容量有限

2、更換設備購車信息不能同步。

 

實現購車商品數據同步:

1、要求用戶登錄。

2、把購物車商品列表保存到數據庫中。推薦使用redis。

3、Key:用戶id,value:購車商品列表。推薦使用hash,hash的field:商品id,value:商品信息。

4、在用戶未登錄情況下寫cookie。當用戶登錄後,訪問購物車列表時,

a)        把cookie中的數據同步到redis。

b)       把cookie中的數據刪除

c)        展示購物車列表時以redis爲準。

d)       如果redis中有數據cookie中也有數據,需要做數據合併。相同商品數量相加,不同商品添加一個新商品。

如果用戶登錄狀態,展示購物車列表以redis爲準。如果未登錄,以cookie爲準。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章