說明:當用戶點擊購物車按鈕時,應該跳轉到購物車列表頁面.
頁面名稱: cart.jsp
頁面數據: ${cartList}html
package com.jt.pojo; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.experimental.Accessors; @TableName("tb_cart") @Data @Accessors(chain = true) public class Cart extends BasePojo{ @TableId(type = IdType.AUTO) //主鍵自增 private Long id; //購物車Id號 private Long userId; //用戶Id號 private Long itemId; //商品id號 private String itemTitle; //商品標題 private String itemImage; //商品圖片信息 private Long itemPrice; private Integer num; }
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <artifactId>jt-cart</artifactId> <parent> <artifactId>jt2007</artifactId> <groupId>com.jt</groupId> <version>1.0-SNAPSHOT</version> </parent> <!--3.依賴工具API--> <dependencies> <dependency> <groupId>com.jt</groupId> <artifactId>jt-common</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> <!--4.添加maven插件--> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
package com.jt.controller; import com.alibaba.dubbo.config.annotation.Reference; import com.jt.pojo.Cart; import com.jt.service.DubboCartService; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import java.util.List; @Controller @RequestMapping("/cart") public class CartController { @Reference(check = false) private DubboCartService cartService; /** * 業務描述: 展示購物車列表頁面,同時查詢購物車數據 * url: http://www.jt.com/cart/show.html * 參數: userId=7L * 返回值: 頁面邏輯名稱 cart.jsp * 頁面取值: ${cartList} */ @RequestMapping("/show") public String show(Model model){ Long userId = 7L; //暫時寫死 List<Cart> cartList = cartService.findCartListByUserId(userId); model.addAttribute("cartList",cartList); return "cart"; } }
package com.jt.service; import com.alibaba.dubbo.config.annotation.Service; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.jt.mapper.CartMapper; import com.jt.pojo.Cart; import org.springframework.beans.factory.annotation.Autowired; import java.util.List; @Service(timeout = 3000) public class DubboCartServiceImpl implements DubboCartService{ @Autowired private CartMapper cartMapper; @Override public List<Cart> findCartListByUserId(Long userId) { QueryWrapper<Cart> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("user_id", userId); return cartMapper.selectList(queryWrapper); } }
1.頁面URL分析
2.商品的參數 在url地址中 RESTFul風格.
3.頁面JS分析java
/** * 業務描述: * 完成購物車數量的修改操做 * url地址: http://www.jt.com/cart/update/num/1474392004/4 * 參數: restFul風格 * 返回值: void */ @RequestMapping("/update/num/{itemId}/{num}") @ResponseBody //讓ajax程序結束 public void updateNum(Cart cart){//springmvc 針對restFul提供的功能 名稱和屬性一致 Long userId = 7L; cart.setUserId(userId); cartService.updateCartNum(cart); }
/** * Sql: update tb_cart set num=#{num},updated=#{updated} * where user_id=#{userId} and item_id = #{itemId} * @param cart */ @Override public void updateCartNum(Cart cart) { Cart cartTemp = new Cart(); cartTemp.setNum(cart.getNum()); QueryWrapper<Cart> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("user_id", cart.getUserId()) .eq("item_id", cart.getItemId()); cartMapper.update(cartTemp,queryWrapper); }
業務邏輯: 當刪除購物車時,應該刪除數據庫記錄,以後將頁面重定向到購物車列表頁面.web
/** * 實現購物車刪除操做 * 1.url地址: http://www.jt.com/cart/delete/1474392004.html * 2.參數: 1474392004 itemId * 3.返回值: String 重定向到列表頁面 */ @RequestMapping("/delete/{itemId}") public String deleteCart(Cart cart){ Long userId = 7L; cart.setUserId(userId); cartService.deleteCart(cart); return "redirect:/cart/show.html"; }
@Override public void deleteCart(Cart cart) { //userId/itemId cartMapper.delete(new QueryWrapper<>(cart)); //根據對象中不爲null的屬性當作where條件. }
業務說明: 當購物車點擊新增時,須要重定向到購物車列表頁面. 完成購物車"新增""
注意事項: 若是用戶重複添加購物車.則只作購物車數量的更新,若是購物車沒有記錄,則新增數據.
2).參數接收ajax
/** * 業務描述: * 實現購物車的新增 * 1.url:http://www.jt.com/cart/add/562379.html * 2.參數: num: 1 * itemTitle: 三星 W999 黑色 電信3G手機 雙卡雙待雙通 * itemImage: https://img14.360buyimg.com/n0/jfs/t1/125477/20/11441/43547/5f4e2293E02391add/cf8bee33b3ed4394.jpg * itemPrice: 4299000 * 3.返回值: String 重定向到購物車頁面 */ @RequestMapping("/add/{itemId}") public String addCart(Cart cart){ Long userId = UserThreadLocal.get().getId(); cart.setUserId(userId); dubboCartService.addCart(cart); return "redirect:/cart/show.html"; }
/** * 若是購物車已存在,則更新數量,不然新增. * 如何判斷購物車數據是否存在 userId itemId * * @param cart */ @Override public void addCart(Cart cart) { //1.查詢購物車信息 userId,itemId QueryWrapper<Cart> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("user_id", cart.getUserId()); queryWrapper.eq("item_id",cart.getItemId()); Cart cartDB = cartMapper.selectOne(queryWrapper); if(cartDB == null){ //第一次新增購物車 cartMapper.insert(cart); }else{ //用戶已經加購,更新數量 int num = cartDB.getNum() + cart.getNum(); Cart cartTemp = new Cart(); cartTemp.setNum(num).setId(cartDB.getId()); cartMapper.updateById(cartTemp); } }
需求: 若是用戶不登陸,則不容許訪問購物車列表頁面,若是沒有登陸則應該重定向到用戶登陸頁面.redis
package com.jt.config; import com.jt.interceptor.UserInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class MvcConfigurer implements WebMvcConfigurer{ //開啓匹配後綴型配置 @Override public void configurePathMatch(PathMatchConfigurer configurer) { configurer.setUseSuffixPatternMatch(true); } //配置攔截器策略 @Autowired private UserInterceptor userInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(userInterceptor) .addPathPatterns("/cart/**","/order/**"); } }
說明:經過攔截器動態獲取userIdspring
package com.jt.interceptor; import com.jt.pojo.User; import com.jt.util.ObjectMapperUtil; import com.jt.util.UserThreadLocal; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.servlet.HandlerInterceptor; import redis.clients.jedis.JedisCluster; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @Component public class UserInterceptor implements HandlerInterceptor { @Autowired private JedisCluster jedisCluster; /** * 參數介紹: * @param request 用戶請求對象 * @param response 服務器響應對象 * @param handler 當前處理器自己 * @return true:請求放行 false:請求攔截 通常配合重定向使用 * @throws Exception * * 若是用戶不登錄則重定向到登錄頁面 * * 判斷用戶是否登陸了? * 依據: 1.根據cookie判斷 * 2.判斷redis */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String ticket = null; //1.判斷cookie中是否有記錄 Cookie[] cookies = request.getCookies(); if (cookies !=null && cookies.length>0){ for (Cookie cookie:cookies) { if ("JT_TICKET".equals(cookie.getName())){ ticket = cookie.getValue(); break; } } } //2.判斷cookie的數據是否有效 if (!StringUtils.isEmpty(ticket)){ //3.判斷redis if (jedisCluster.exists(ticket)){ String userJSON = jedisCluster.get(ticket); User user = ObjectMapperUtil.toObject(userJSON, User.class); //4.利用request對象進行數據傳遞 request是最經常使用的方式 request.setAttribute("JT_USER", user); //5.利用本地線程變量傳參(兩種方式均可以,第二種更便捷,可是微服務中須要謹慎,只在同一線程內有效) UserThreadLocal.set(user); return true; //表示用戶已登錄 放行 } } //重定向到用戶登陸頁面 response.sendRedirect("/user/login.html"); return false;//表示攔截 } /** * 爲了知足業務須要將數據刪除 */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { request.removeAttribute("JT_USER"); UserThreadLocal.remove(); } }
名稱: 本地線程變量
做用: 能夠在同一個線程內,實現數據的共享.
![Image \[2\].png](/img/bVcHRC0)數據庫
package com.jt.util; import com.jt.pojo.User; public class UserThreadLocal{ //在同一線程內有效 private static ThreadLocal<User> userThreadLocal = new ThreadLocal<>(); //存值 public static void set(User user){ userThreadLocal.set(user); } //取值 public static User get(){ return userThreadLocal.get(); } //刪除 public static void remove(){ userThreadLocal.remove(); } }
![Image \[3\].png](/img/bVcHRDp)apache
![Image \[4\].png](/img/bVcHRDu)服務器
![Image \[5\].png](/img/bVcHRDv)cookie
![Image \[6\].png](/img/bVcHRD0)
<!--繼承父級項目--> <parent> <artifactId>jt2007</artifactId> <groupId>com.jt</groupId> <version>1.0-SNAPSHOT</version> </parent> <!--依賴工具API--> <dependencies> <dependency> <groupId>com.jt</groupId> <artifactId>jt-common</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> <!--添加maven插件--> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
![Image \[7\].png](/img/bVcHREf)
刪除orderItem的主鍵標識
![Image \[8\].png](/img/bVcHREx)
訂單項目代碼結構以下
![Image \[9\].png](/img/bVcHREC)
![Image \[10\].png](/img/bVcHREG)
![Image \[11\].png](/img/bVcHREV)
![Image \[12\].png](/img/bVcHRFJ)
![Image \[13\].png](/img/bVcHRFL)
![Image \[14\].png](/img/bVcHRF6)
![Image \[15\].png](/img/bVcHRGd)
package com.jt.controller; import com.alibaba.dubbo.config.annotation.Reference; import com.jt.pojo.Cart; import com.jt.pojo.Order; import com.jt.service.DubboCartService; import com.jt.service.DubboOrderService; import com.jt.util.UserThreadLocal; import com.jt.vo.SysResult; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import java.util.List; @Controller @RequestMapping("/order") public class OrderController { @Reference private DubboCartService dubboCartService; @Reference private DubboOrderService dubboOrderService; /** * 個人訂單頁面跳轉 * url:http://www.jt.com/order/myOrder.html * 參數:無 * 返回值: 個人訂單頁面 * 頁面數據: */ @RequestMapping("/myOrder") public String myOrder(){ return "my-orders"; } /** * 完成訂單查詢 * url:http://www.jt.com/order/success.html?id=order.getUserId()1605862542149 * 參數: orderId * 返回值: 訂單成功頁面 * 頁面取值:${order.orderId} */ @RequestMapping("/success") public String success(String id,Model model){ Order order = dubboOrderService.findOrderId(id); model.addAttribute("order", order); return "success"; } /** * 訂單提交入庫操做 * url:http://www.jt.com/order/submit * 參數: 整個表單對象 order * 返回值:SysResult對象(orderId) */ @RequestMapping("/submit") @ResponseBody public SysResult saveOrder(Order order){ Long userId =UserThreadLocal.get().getId(); order.setUserId(userId); String orderId = dubboOrderService.saveOrder(order); if ((StringUtils.isEmpty(orderId))){ return SysResult.fail(); }else { return SysResult.success(orderId); } } /** * 跳轉訂單確認頁面 * url:http://www.jt.com/order/create.html * 參數:暫時沒有 * 返回值: order-cart.jsp */ @RequestMapping("/create") public String create(Model model){ Long userId = UserThreadLocal.get().getId(); List<Cart> carts = dubboCartService.findCartListByUserId(userId); model.addAttribute("carts", carts); return "order-cart"; } }
package com.jt.service; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.jt.pojo.Order; import com.jt.pojo.OrderItem; import com.jt.pojo.OrderShipping; import org.springframework.beans.factory.annotation.Autowired; import com.alibaba.dubbo.config.annotation.Service; import com.jt.mapper.OrderItemMapper; import com.jt.mapper.OrderMapper; import com.jt.mapper.OrderShippingMapper; import org.springframework.transaction.annotation.Transactional; import java.util.List; @Service(timeout = 3000) public class OrderServiceImpl implements DubboOrderService { @Autowired private OrderMapper orderMapper; @Autowired private OrderShippingMapper orderShippingMapper; @Autowired private OrderItemMapper orderItemMapper; /** * 完成三張表的入庫 * @param order * @return */ @Override @Transactional //控制事務 public String saveOrder(Order order) { //訂單號:登陸用戶id+當前時間戳 String orderId = order.getUserId().toString() + System.currentTimeMillis(); order.setOrderId(orderId).setStatus(1); orderMapper.insert(order); OrderShipping orderShipping = order.getOrderShipping(); orderShipping.setOrderId(orderId); orderShippingMapper.insert(orderShipping); List<OrderItem> orderItems = order.getOrderItems(); for (OrderItem orderItem:orderItems){ orderItem.setOrderId(orderId); orderItemMapper.insert(orderItem); } return orderId; } //須要經過order對象 返回三部分數據 @Override public Order findOrderId(String id) { Order order = orderMapper.selectById(id); OrderShipping orderShipping = orderShippingMapper.selectById(id); QueryWrapper queryWrapper = new QueryWrapper(); queryWrapper.eq("order_id", id); List<OrderItem> orderItems = orderItemMapper.selectList(queryWrapper); order.setOrderShipping(orderShipping).setOrderItems(orderItems); return order; } }
![Image \[16\].png](/img/bVcHRGp)