购物车操作
业务剖析
阐明:当用户点击购物车按钮时,应该跳转到购物车列表页面.
页面名称: cart.jsp
页面数据: ${cartList}
创立购物Cart POJO
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;}
创立JT-CART我的项目
创立我的项目
增加继承依赖插件
<?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>
购物车我的项目构造
购物车业务实现
购物车列表展示
编辑CartController
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"; }}
编辑CartService
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); }}
页面成果展示
购物车数量的批改
页面URL剖析
1.页面URL剖析
2.商品的参数 在url地址中 RESTFul格调.
3.页面JS剖析
编辑CartController
/** * 业务形容: * 实现购物车数量的批改操作 * 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); }
编辑CartService
/** * 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); }
购物车删除
页面剖析
业务逻辑: 当删除购物车时,应该删除数据库记录,之后将页面重定向到购物车列表页面.
编辑CartController
/** * 实现购物车删除操作 * 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"; }
编辑CartService
@Override public void deleteCart(Cart cart) { //userId/itemId cartMapper.delete(new QueryWrapper<>(cart)); //依据对象中不为null的属性当做where条件. }
购物车新增
业务阐明
业务阐明: 当购物车点击新增时,须要重定向到购物车列表页面. 实现购物车"新增""
注意事项: 如果用户反复增加购物车.则只做购物车数量的更新,如果购物车没有记录,则新增数据.
2).参数接管
编辑CartController
/*** 业务形容:* 实现购物车的新增* 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";}
编辑CartService
/** * 如果购物车已存在,则更新数量,否则新增. * 如何判断购物车数据是否存在 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); } }
权限管制
需要: 如果用户不登录,则不容许拜访购物车列表页面,如果没有登录则应该重定向到用户登录页面.
SpringMVC调用原理图
拦截器工作原理
编辑拦截器配置
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;@Configurationpublic 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/**"); }}
编辑拦截器
阐明:通过拦截器动静获取userId
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;@Componentpublic 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(); }}
ThreadLocal介绍
ThreadLocal作用
名称: 本地线程变量
作用: 能够在同一个线程内,实现数据的共享.
![Image \[2\].png](/img/bVcHRC0)
编辑ThreadLocal工具API
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(); }}
重构User拦截器
![Image \[3\].png](/img/bVcHRDp)
动静获取UserId
![Image \[4\].png](/img/bVcHRDu)
京淘订单模块
订单表设计
![Image \[5\].png](/img/bVcHRDv)
创立订单我的项目
创立我的项目
![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>
增加POJO
![Image \[7\].png](/img/bVcHREf)
删除orderItem的主键标识
![Image \[8\].png](/img/bVcHREx)
构建jt-order我的项目
订单我的项目代码构造如下
![Image \[9\].png](/img/bVcHREC)
订单确认页面跳转
url剖析
![Image \[10\].png](/img/bVcHREG)
页面成果展示
![Image \[11\].png](/img/bVcHREV)
对于订单提交
页面URL阐明
![Image \[12\].png](/img/bVcHRFJ)
申请参数
![Image \[13\].png](/img/bVcHRFL)
订单胜利跳转
页面url剖析
![Image \[14\].png](/img/bVcHRF6)
页面成果展示
![Image \[15\].png](/img/bVcHRGd)
编辑OrderController
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"; }}
编辑OrderService
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)