购物车操作

业务剖析

阐明:当用户点击购物车按钮时,应该跳转到购物车列表页面.

页面名称: 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)