SpringBoot part4 day19

1 购物车订单删除

1.1页面分析

在这里插入图片描述

1.2 jt-web CartController

在这里插入图片描述

@Reference(check=false)
    private DubboCatService cartService;
   /**
    * 删除页面  cart/delete/${cart.itemId}.html
    * 请求参数:itemId/userId
    * 返回值结果:重定向到系统首页
    * */
   @RequestMapping("/delete/{itemId}")
   public  String doDeleteCard(Cart cart){
      Long userId = 7L;
      cart.setUserId(userId);
      cartService.deleteCart(cart);
      return "redirect:/cart/show.html";
   }

1.3 jt-cart DubboCartService

//删除购物车商品信息
    @Override
    public void deleteCart(Cart cart) {
      
        cartMapper.delete(new QueryWrapper<>(cart));
    }

1.4购物车权限控制

1.4.1 需求说明
当用户在没有登陆的条件下不允许访问敏感业务,购物车操作/订单操作等 使用拦截器机制
过滤器:过滤url请求,一般不做业务处理
拦截器:在服务器工作前进行拦截,或者服务器返回数据后进行拦截进行数据处理
一共三个拦截:服务器执行之前,服务器返回数据之后,用户拿到数据之前
早期在Xml进行配置,springBoot都是用配置类
在这里插入图片描述 在这里插入图片描述
1.4.2创建包结构
在这里插入图片描述
添加拦截器

package com.jt.interceptor;

import com.jt.util.CookieUtil;
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//将拦截器交给spring容器管理
public class UserInterceptor implements HandlerInterceptor {
    private static final String JT_TICKET="JT_TICKET";
    @Autowired
    private JedisCluster jedisCluster;
    /**
     * 返回值说明:
     *     1.false  表示拦截  一般都要配合重定向使用
     *     2.true   表示放行
     *  如何实现业务:
     *      判断用户是否登陆???Cookie数据  检查redis中的数据
     *      重定向到系统登陆页面
     * @param   request
     * @param   response
     * @param   handler
     * throws Exception
     * */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.检验Cookie中是否有结果
       Cookie cookie= CookieUtil.getCookie(request, JT_TICKET);
        //2.校验Cookie是否有效
        if(cookie!=null){
          String ticket=cookie.getValue();
          if(StringUtils.hasLength(ticket)){
             //校验redis中是否有结果
              if(jedisCluster.exists(ticket)){
                 //用户存在,直接返回true
                  return true;
              }

          }
              //没有结果,cookie中数据有误,需要删除cookie
              CookieUtil.addCookie(response, JT_TICKET, "", "*", "jt.com", 0);

        }
        //3.如果数据为空,重定向到系统首页
        response.sendRedirect("/user/login.html");
        return false;  //表示拦截
    }
}

添加拦截器配置
在这里插入图片描述

	//添加拦截器配置
	@Autowired
	private UserInterceptor userInterceptor;
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(userInterceptor)
				.addPathPatterns("/cart/**","/order/**");
	}

1.5 动态获取userId

在拦截其中获取用户信息
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package com.jt.interceptor;

import com.jt.pojo.User;
import com.jt.util.CookieUtil;
import com.jt.util.ObjectMapperUtil;
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//将拦截器交给spring容器管理
public class UserInterceptor implements HandlerInterceptor {
    private static final String JT_TICKET="JT_TICKET";
    @Autowired
    private JedisCluster jedisCluster;
    /**
     * 返回值说明:
     *     1.false  表示拦截  一般都要配合重定向使用
     *     2.true   表示放行
     *  如何实现业务:
     *      判断用户是否登陆???Cookie数据  检查redis中的数据
     *      重定向到系统登陆页面
     * @param   request
     * @param   response
     * @param   handler
     * throws Exception
     * */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.检验Cookie中是否有结果
       Cookie cookie= CookieUtil.getCookie(request, JT_TICKET);
        //2.校验Cookie是否有效
        if(cookie!=null){
          String ticket=cookie.getValue();
          if(StringUtils.hasLength(ticket)){
             //校验redis中是否有结果
              if(jedisCluster.exists(ticket)){
                  //获取user信息

                  String json=jedisCluster.get(ticket);
                  User user= ObjectMapperUtil.toObject(json,User.class);
                  //获取到的对象如何传输?????request
                  request.setAttribute("JT_USER", user);
                 //用户存在,直接返回true
                  return true;
              }

          }
              //没有结果,cookie中数据有误,需要删除cookie
              CookieUtil.addCookie(response, JT_TICKET, "", "*", "jt.com", 0);

        }
        //3.如果数据为空,重定向到系统首页
        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");
    }
}

2 ThreadLocal介绍

本地线程变量

2.1工作原理

作用: 在线程内部(一个线程)实现数据的共享
request 对象只有在@controller表示的类中才能获取
threadLocal没有线程安全问题 作用 : 在线程内部实现数据共享
在这里插入图片描述

2.2工具API编辑

jt-web中
在这里插入图片描述

package com.jt.util;

import com.jt.pojo.User;

public class UserThreadLocal {
    private static ThreadLocal<User> threadLocal=new ThreadLocal<User>();
    public static void setUser(User user){

        threadLocal.set(user);
    }
    public static User getUser(){
        return threadLocal.get();
    }
    public static void remove(){
        threadLocal.remove();
    }

}

微服务中Dubbo开启另一个线程执行任务
思考题: JT-WEB中ThreadLocal.set(xxx),问 在jt-cart中的service能否执行ThreadLocal.get()???
A. 不能
在这里插入图片描述
在这里插入图片描述

由于内存的泄漏,所以对加入ThreadLocal中数据要进行删除
重构拦截器工具API

package com.jt.interceptor;

import com.jt.pojo.User;
import com.jt.util.CookieUtil;
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//将拦截器交给spring容器管理
public class UserInterceptor implements HandlerInterceptor {
    private static final String JT_TICKET="JT_TICKET";
    @Autowired
    private JedisCluster jedisCluster;
    /**
     * 返回值说明:
     *     1.false  表示拦截  一般都要配合重定向使用
     *     2.true   表示放行
     *  如何实现业务:
     *      判断用户是否登陆???Cookie数据  检查redis中的数据
     *      重定向到系统登陆页面
     * @param   request
     * @param   response
     * @param   handler
     * throws Exception
     * */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.检验Cookie中是否有结果
       Cookie cookie= CookieUtil.getCookie(request, JT_TICKET);
        //2.校验Cookie是否有效
        if(cookie!=null){
          String ticket=cookie.getValue();
          if(StringUtils.hasLength(ticket)){
             //校验redis中是否有结果
              if(jedisCluster.exists(ticket)){
                  //获取user信息

                  String json=jedisCluster.get(ticket);
                  User user= ObjectMapperUtil.toObject(json,User.class);
                  //获取到的对象如何传输?????request
                  request.setAttribute("JT_USER", user);

                 UserThreadLocal.setUser(user);
                  //用户存在,直接返回true
                  return true;
              }

          }
              //没有结果,cookie中数据有误,需要删除cookie
              CookieUtil.addCookie(response, JT_TICKET, "", "*", "jt.com", 0);

        }
        //3.如果数据为空,重定向到系统首页
        response.sendRedirect("/user/login.html");
        return false;  //表示拦截
    }



    //为了防止内存泄漏,将多余数据删除
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //移除request对象
        request.removeAttribute("JT_USER");
        //移除threadLocal数据
        UserThreadLocal.remove();
    }
}

对购物车所有功能中的user进行动态获取

package com.jt.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.jt.pojo.Cart;
import com.jt.pojo.User;
import com.jt.service.DubboCatService;
import com.jt.util.UserThreadLocal;
import com.jt.vo.SysResult;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

@Controller
@RequestMapping("/cart")
public class CartController {

   @Reference(check=false)
    private DubboCatService cartService;
   /**
    * 删除页面  cart/delete/${cart.itemId}.html
    * 请求参数:itemId/userId
    * 返回值结果:重定向到系统首页
    * */
   @RequestMapping("/delete/{itemId}")
   public  String doDeleteCard(Cart cart){
      Long userId= UserThreadLocal.getUser().getId();
      cart.setUserId(userId);
      cartService.deleteCart(cart);
      return "redirect:/cart/show.html";
   }

   /**
    *
    * */
   @RequestMapping("/add/{itemId}")
   public String saveCart(Cart cart){
      Long userId= UserThreadLocal.getUser().getId();
      cart.setUserId(userId);
      cartService.saveCart(cart);
      return "redirect:/cart/show.html";

   }
   /**
    * 购物车商品数量更新操作
    *  业务需求: 实现商品数量的更新操作
    *  url:http://www.jt.com/cart/update/num/1474391990/10
    *  参数: userId=7/itemId/num
    *  返回值: void
    *
    *  用法: 如果restFul参数名称与对象的属性名称一致,则可以使用对象的方式接收
    * */
   @RequestMapping("/update/num/{itemId}/{num}")
   @ResponseBody//1.将数据用json返回  2.表示ajax请求结束
   public void doupdateCartNum(Cart cart){
      Long userId= UserThreadLocal.getUser().getId();
      cart.setUserId(userId);
      cartService.updateCartNum(cart);

   }


   /**
    * 展现购物车列表信息
    *  http://www.jt.com/cart/show.html
    *  参数:  必须获取userId=7L
    *  返回值:cart.jsp
    *  页面取值参数${cartList}
    * */
   @RequestMapping("/show")
    public String doFindCart(Model model, HttpServletRequest request){
       // User user=(User)request.getAttribute("JT_USER");

       Long userId= UserThreadLocal.getUser().getId();  //暂时写死,后期维护
       List<Cart> cartList=cartService.findCartList(userId);
       model.addAttribute("cartList", cartList);

       return "cart";
   }


}

3 商品订单的实现

3.1订单确认页面的跳转

3.1.1 需求的分析:
页面跳转: order-cart.jsp页面,需要展现商品数据信息,同时有收件人地址信息.在这里插入图片描述
3.1.2jt-web新建OrderController

package com.jt.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.jt.pojo.Cart;
import com.jt.service.DubboCatService;
import com.jt.util.UserThreadLocal;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;

@Controller
@RequestMapping("/order")
public class OrderController {
     @Reference(check = false)
     private DubboCatService cartsrvice;

    /**
     * 1.实现订单确认页面跳转
     * url地址: http://www.jt.com/order/create.html
     * 参数说明:  获取userId
     * 返回值结果: 订单确认页面  order-cart.jsp
     * 页面取值方式:  ${carts}
     */
    @RequestMapping("/create")
    public String doFindOrderCart(Model model){
        long userId= UserThreadLocal.getUser().getId();;
        List<Cart> cartList=cartsrvice.findCartList(userId);
         model.addAttribute("carts", cartList);
        return "order-cart";
    }


}

测试结果
在这里插入图片描述

3.2 创建订单项目

3.2.1订单模块表设计
在这里插入图片描述
3.2.2在jt-common中导入pojo对象
在这里插入图片描述

package com.jt.pojo;


import java.util.Date;
import java.util.List;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

import lombok.Data;
import lombok.experimental.Accessors;

@TableName("tb_order")
@Data
@Accessors(chain=true)
public class Order extends BasePojo{
	@TableField(exist=false)	//入库操作忽略该字段
	private OrderShipping orderShipping;
								//封装订单商品信息  一对多
	@TableField(exist=false)	//入库操作忽略该字段
	private List<OrderItem> orderItems;
	
	@TableId
    private String orderId;
    private String payment;
    private Integer paymentType;
    private String postFee;
    private Integer status;
    private Date paymentTime;
    private Date consignTime;
    private Date endTime;
    private Date closeTime;
    private String shippingName;
    private String shippingCode;
    private Long userId;
    private String buyerMessage;
    private String buyerNick;
    private Integer buyerRate;

}
package com.jt.pojo;


import java.util.Date;
import java.util.List;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

import lombok.Data;
import lombok.experimental.Accessors;
@TableName("tb_order_item")
@Data
@Accessors(chain=true)
public class OrderItem extends BasePojo{
	

    private String itemId;

    private String orderId;

    private Integer num;

    private String title;

    private Long price;

    private Long totalFee;

    private String picPath;
}
package com.jt.pojo;


import java.util.Date;
import java.util.List;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

import lombok.Data;
import lombok.experimental.Accessors;
@TableName("tb_order_shipping")
@Data
@Accessors(chain=true)
public class OrderShipping extends BasePojo{
	
	@TableId
    private String orderId;

    private String receiverName;

    private String receiverPhone;

    private String receiverMobile;

    private String receiverState;

    private String receiverCity;

    private String receiverDistrict;

    private String receiverAddress;

    private String receiverZip;
    
}

在这里插入图片描述

3.3定义服务提供者jt-order

在这里插入图片描述

server:
  port: 8095
  servlet:
    context-path: /
spring:
  datasource:
    #引入druid数据源
    #type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3307/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
    #url: jdbc:mysql://192.168.126.129:8066/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
    username: root
    password: root

  mvc:
    view:
      prefix: /WEB-INF/views/
      suffix: .jsp
#mybatis-plush配置
mybatis-plus:
  type-aliases-package: com.jt.pojo
  mapper-locations: classpath:/mybatis/mappers/*.xml
  configuration:
    map-underscore-to-camel-case: true

#关于Dubbo配置
dubbo:
  scan:
    basePackages: com.jt    #指定dubbo的包路径
  application:              #应用名称
    name: provider-order     #一个接口对应一个服务名称
  registry:
    address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183
  protocol:  #指定协议
    name: dubbo  #使用dubbo协议(tcp-ip)  web-controller直接调用sso-Service
    port: 20883  #每一个服务都有自己特定的端口 不能重复.


logging:
  level: 
    com.jt.mapper: debug

 <!--添加依赖-->
    <dependencies>
        <dependency>
            <groupId>com.jt</groupId>
            <artifactId>jt-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

在这里插入图片描述

3.4SpringMVC参数传递说明

3.4.1简单参数赋值

<input type="text" name="name" value="二郎神">
<input type="text" name="age" value="18">
public void doFindUser(String name,Integer age){

}

3.4.2对象赋值

<input type="text" name="name" value="二郎神">
<input type="text" name="age" value="18">
<input type="text" name="sex" value="男">
public void doFindUser(User user){

}

3.4.3对象引用赋值

<input type="text" name="name" value="二郎神">
<input type="text" name="age" value="18">
<input type="text" name="name" value="哮天犬">
<input type="text" name="age" value="15">

问题:如果页面中有重名属性
解决方案:利用对象的引用封装

class Dog{
  private String name;
  private Integer age; 
}
class User{
  private String name;
  private Integer age;
  private Dog dog;
}
<input type="text" name="name" value="二郎神">
<input type="text" name="age" value="18">
<input type="text" name="dog.name" value="哮天犬">
<input type="text" name="dog.age" value="15">

public void doGetUser(User user){

}

给list集合传递参数:

class Dog{
  private String name;
  private Integer age; 
}
class User{
  private String name;
  private Integer age;
  private Dog dog;
  private List<String> hobbys;
}
<input type="text" name="name" value="二郎神">
<input type="text" name="age" value="18">
<input type="text" name="dog.name" value="哮天犬">
<input type="text" name="dog.age" value="15">
<input type="text" name="hobbys[0]" value="敲代码">
<input type="text" name="hobbys[1]" value="学java">


3.5订单入库的实现

3.5.1 业务分析
1)url
在这里插入图片描述
2).页面参数分析

在这里插入图片描述

3).页面结构分析
在这里插入图片描述
在这里插入图片描述
4).POJO对象赋值
在这里插入图片描述
5).页面JS分析
在这里插入图片描述

表单数据序列化:
在这里插入图片描述
OrderController

     @Reference(check = false)
     private DubboOrderService orderService;

 @RequestMapping("/submit")
     @ResponseBody
     public SysResult doSubmit(Order order){
         long userId=UserThreadLocal.getUser().getId();
         order.setUserId(userId);
         String orderId=orderService.saveOrder(order);
         if(StringUtils.hasLength(orderId))
            return SysResult.success(orderId);
            return SysResult.fail();
     }

DubboOrderServiceImpl

package com.jt.service;

import com.alibaba.dubbo.config.annotation.Service;
import com.jt.mapper.OrderItemMapper;
import com.jt.mapper.OrderMapper;
import com.jt.mapper.OrderShippingMapper;
import com.jt.pojo.Order;
import com.jt.pojo.OrderItem;
import com.jt.pojo.OrderShipping;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

@Service(timeout=3000)
public class DubboOrderServiceImpl implements DubboOrderService{
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderItemMapper orderItemMapper;
    @Autowired
    private OrderShippingMapper orderShippingMapper;

    @Override
     @Transactional
    public String saveOrder(Order order) {
        //字符串拼接
        String orderId=order.getUserId()+""+System.currentTimeMillis();
        //1.完成订单入库操作
        order.setOrderId(orderId).setStatus(1);//未付款状态
        orderMapper.insert(order);
        //2.订单物流入库
        OrderShipping orderShipping=order.getOrderShipping();
        orderShipping.setOrderId(orderId);
        orderShippingMapper.insert(orderShipping);
        //3.订单商品的入库
        List<OrderItem> lists=order.getOrderItems();
        for (OrderItem orderItem : lists) {
            orderItem.setOrderId(orderId);

            orderItemMapper.insert(orderItem);
        }

        return orderId;
    }
}

3.6订单的查询

3.6.1页面分析
在这里插入图片描述
编辑OrderController

/**
      * 实现订单页面的查询
      * http://www.jt.com/order/success.html?id=71608193982133
      *页面取值:order对象及封装的两个属性
      * */
     @RequestMapping("/success")
      public String doSuccess(@RequestParam("id") String orderId,Model model){//将id赋值给orderId
        Order order=orderService.findOrderById(orderId);
         model.addAttribute("order",order);
        return "success";
     }

编辑OrderService

 @Override
    public Order findOrderById(String orderId) {
        //查询订单商品信息
        QueryWrapper<OrderItem> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("order_id", orderId);
       List<OrderItem> orderItemLists=orderItemMapper.selectList(queryWrapper);
       //查询物流信息
       OrderShipping orderShipping=orderShippingMapper.selectById(orderId);
       //查询订单信息
       Order order=orderMapper.selectById(orderId);
       //数据包装
       order.setOrderItems(orderItemLists).setOrderShipping(orderShipping);

        return order;
    }

测试效果:
在这里插入图片描述
项目的梳理:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值