【項目學習】穀粒商城學習記錄8 - 購物車
本節起將不對一些重複細節進行詳細說明
一、環境搭建 & 準備工作
1.1. 創建新模塊
- 注意java版本信息後面在pom.xml文件裏修改
- 導入公共模塊依賴
- 寫配置信息
- 啓動類加上註冊發現和Feign功能
- 修改網關
- id: gulimall_cart_route uri: lb://gulimall-cart predicates: - Host=cart.gulimall.cn
1.2. 靜態頁面搭建
- 設置域名
- 將註冊頁面和登錄頁面放在服務資源目錄下
- 登錄、註冊頁面動靜分離,將靜態資源移到nginx下
- 修改頁面內的路徑
- 測試:
1.3. 數據存儲結構:
1.4. 完善頁面細節,實現頁面跳轉
二、ThreadLocal 用戶身份鑑別
-
創建service.CartService和impl.CartServiceImpl
-
創建攔截器interceptor.CartInterceptor
-
實現攔截器在業務執行前的功能:
public class CartInterceptor implements HandlerInterceptor { public static ThreadLocal<UserInfoTo> threadLocal = new ThreadLocal<>(); /** * 目標方法執行之前 * @param request * @param response * @param handler * @return * @throws Exception */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { UserInfoTo userInfoTo = new UserInfoTo(); HttpSession session = request.getSession(); MemberRespVo member = (MemberRespVo) session.getAttribute(AuthServerConstant.LOGIN_USER); if(member != null) { //用戶登錄了 userInfoTo.setUserId(member.getId()); } Cookie[] cookies = request.getCookies(); if(cookies != null && cookies.length > 0) { for (Cookie cookie : cookies) { //user-key String name = cookie.getName(); if(name.equals(CartConstant.TEMP_USER_COOKIE_NAME)) { userInfoTo.setUserKey(cookie.getValue()); userInfoTo.setTempUser(true); } } } //如果沒有臨時用戶一定分配一個臨時用戶 if(StringUtils.isEmpty(userInfoTo.getUserKey())) { String uuid = UUID.randomUUID().toString(); userInfoTo.setUserKey(uuid); } //目標方法執行之前 threadLocal.set(userInfoTo); return true; } }
-
ThreadLocal能夠在整個線程內共享數據
-
測試:
-
實現攔截器在業務處理後的功能
/** * 業務執行之後,分配臨時用戶,讓瀏覽器保存 * @param request * @param response * @param handler * @param modelAndView * @throws Exception */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { UserInfoTo userInfoTo = threadLocal.get(); if(!userInfoTo.isTempUser()) { Cookie cookie = new Cookie(CartConstant.TEMP_USER_COOKIE_NAME, userInfoTo.getUserKey()); cookie.setDomain("gulimall.com"); cookie.setMaxAge(CartConstant.TEMP_USER_COOKIE_TIMEOUT); response.addCookie(cookie); } }
-
測試:
三、實現添加購物車功能
-
商品詳情頁點擊添加購物車後,將傳遞skuId和numInput兩個參數
-
測試
登陸後不再使用臨時用戶
-
爲了避免鏈接被多次刷新,使用頁面重定向的方式。即添加後重定向到展示頁面
- 代碼
/** * 添加商品到購物車 * @return */ @GetMapping("/addToCart") public String addToCart(@RequestParam("skuId") Long skuId, @RequestParam("num") Integer num, RedirectAttributes ra) throws ExecutionException, InterruptedException { cartService.addToCart(skuId, num); ra.addAttribute("skuId", skuId); return "redirect:/addToCartSuccess.html"; } @GetMapping("/addToCartSuccess.html") public String addToCartSuccessPage(@RequestParam("skuId") Long skuId, Model model) { //重定向到成功頁面,查詢購物車數據 CartItem cartItem = cartService.getCartItem(skuId); model.addAttribute("item", cartItem); return "success"; }
getCartItem
方法具體實現@Override public CartItem getCartItem(Long skuId) { BoundHashOperations<String, Object, Object> cartOps = getCartOps(); String str = (String) cartOps.get(skuId.toString()); CartItem cartItem = JSON.parseObject(str, CartItem.class); return cartItem; }
- 代碼
-
實現獲取購物車,合併購物車功能
- 測試:
實現購物車合併成功
- 測試:
-
實現修改購物車狀態
- 前端頁面綁定點擊事件
$(".itemCheck").click(function () { var skuId = $(this).attr("skuId"); var check = $(this).prop("checked"); location.href = "http://cart.gulimall.com/checkItem?skuId="+skuId+"&check="+(check ? 1 : 0); })
- controller層
/** * 修改購物項選擇狀態 * @param skuId * @param check * @return */ @GetMapping("/checkItem") public String checkItem(@RequestParam("skuId") Long skuId, @RequestParam("check") Integer check) { cartService.checkItem(skuId, check); return "redirect:http://cart.gulimall.com/cart.html"; }
- 具體實現
@Override public void checkItem(Long skuId, Integer check) { BoundHashOperations<String, Object, Object> cartOps = getCartOps(); CartItem cartItem = getCartItem(skuId); cartItem.setCheck(check == 1); String s = JSON.toJSONString(cartItem); cartOps.put(skuId.toString(), s); }
- 前端頁面綁定點擊事件
-
實現增減購物車選項數量
- 前端修改
$(".countOpsBtn").click(function () { var skuId = $(this).parent().attr("skuId"); var num = $(this).parent().find(".countOpsNum").text(); location.href = "http://cart.gulimall.com/countItem?skuId="+skuId+"&num="+num; })
- controller層
/** * 修改購物車選項數量 * @param skuId * @param num * @return */ @GetMapping("/countItem") public String countItem(@RequestParam("skuId") Long skuId, @RequestParam("num") Integer num) { cartService.changeItemCount(skuId, num); return "redirect:http://cart.gulimall.com/cart.html"; }
- 具體實現
/** * 修改購物選項數量 * @param skuId * @param num */ @Override public void changeItemCount(Long skuId, Integer num) { BoundHashOperations<String, Object, Object> cartOps = getCartOps(); CartItem cartItem = getCartItem(skuId); cartItem.setCount(num); String s = JSON.toJSONString(cartItem); cartOps.put(skuId.toString(), s); }
- 前端修改
-
實現刪除購物車選項功能
- 前端修改:
var deleteId = 0; //刪除購物項 function deleteItem() { location.href = "http://cart.gulimall.com/deleteItem?skuId="+deleteId; } $(".deleteItemBtn").click(function () { deleteId = $(this).attr("skuId"); })
- controller
/** * 刪除購物車選項 * @param skuId * @return */ @GetMapping("/deleteItem") public String deleteItem(@RequestParam("skuId") Long skuId) { cartService.deleteItem(skuId); return "redirect:http://cart.gulimall.com/cart.html"; }
- 具體實現
/** * 刪除購物車選項 * @param skuId */ @Override public void deleteItem(Long skuId) { BoundHashOperations<String, Object, Object> cartOps = getCartOps(); cartOps.delete(skuId.toString()); }
- 前端修改: