京淘项目Day20

本文详细介绍了电商网站购物车的操作,包括数量更新和删除,涉及到前端交互、后端控制器和服务的实现。同时,阐述了权限控制机制,使用Spring MVC拦截器判断用户登录状态,并利用ThreadLocal在请求间共享数据。最后,讨论了订单创建、提交及查询的流程,包括前端表单处理、后端服务的事务控制和数据存储。
摘要由CSDN通过智能技术生成

1.完成京淘购物车操作

1.1 数量更新操作

1.1.1 页面分析

1).页面URL分析
在这里插入图片描述

2).页面html分析

<div class="quantity-form" data-bind="">
    <a href="javascript:void(0);" class="decrement" clstag="clickcart|keycount|xincart|diminish1" id="decrement">-</a>
    <input type="text" class="quantity-text" itemPrice="${cart.itemPrice}" itemId="${cart.itemId}" value="${cart.num }" id="changeQuantity-11345721-1-1-0">
    <a href="javascript:void(0);" class="increment" clstag="clickcart|keycount|xincart|add1" id="increment">+</a>
</div>

3).页面JS

$(".increment").click(function(){//+
			var _thisInput = $(this).siblings("input");
			_thisInput.val(eval(_thisInput.val()) + 1);
			$.post("/cart/update/num/"+_thisInput.attr("itemId")+"/"+_thisInput.val(),function(data){
				TTCart.refreshTotalPrice();
			});
		});

1.1.3 编辑CartController

/**
     * 购物车数量更新操作
     * URL地址: http://www.jt.com/cart/update/num/1474391990/16
     * 参数:    itemId,num
     * 返回值:  没有 void
     */
    @RequestMapping("/update/num/{itemId}/{num}")
    @ResponseBody //将返回值转化为json   代表ajax程序结束
    public void updateNum(Cart cart){

        long userId = 7;
        cart.setUserId(userId);
        cartService.updateNum(cart);
    }

1.1.2 编辑CartService

 //sql: update tb_cart set num=#{num},updated=#{updated} where user_id=#{userId} and
    //     item_id = #{itemId}
    @Override
    public void updateNum(Cart cart) {
        Cart temp = new Cart();
        temp.setNum(cart.getNum());
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("user_id", cart.getUserId());
        queryWrapper.eq("item_id", cart.getItemId());
        cartMapper.update(temp,queryWrapper);
    }

1.2 购物车删除操作

1.2.1 页面分析

业务说明: 当用户点击删除按钮时,应该重定向到购物车展现页面.
在这里插入图片描述

1.2.2 编辑CartController

 /**
     * URL地址:http://www.jt.com/cart/delete/1474391990.html
     * 返回值:  String类型
     */
    @RequestMapping("/delete/{itemId}")
    public String deleteCart(Cart cart){

        long userId = 7;
        cart.setUserId(userId);
        cartService.deleteCart(cart);
        return "redirect:/cart/show.html";
    }

1.2.3 编辑CartService

  @Override
    public void deleteCart(Cart cart) {
        //根据对象中不为null的属性充当where条件
        cartMapper.delete(new QueryWrapper<>(cart));
    }

2 关于前台权限控制

2.1 业务说明

当用户在没有登录的条件下,不允许访问敏感业务数据例如购物车/订单业务等…
难点:
1.如何判断用户是否登录? 1.检查cookie 2.检查redis
2.如何控制权限? 拦截器!

2.2 拦截器业务实现原理

2.2.1 SpringMVC流程图复习

在这里插入图片描述

2.2.2 拦截器工作流程

在这里插入图片描述

2.2.3 配置拦截器

在这里插入图片描述

2.2.4 编辑拦截器接口

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 org.springframework.web.servlet.ModelAndView;
import redis.clients.jedis.JedisCluster;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.function.Predicate;
@Component  //将对象交给Spring容器管理
public class UserInterceptor implements HandlerInterceptor {

    @Autowired
    private JedisCluster jedisCluster;

    /**
     * 通过拦截器实现拦截,重定向系统登录页面
     * @param request
     * @param response
     * @param handler
     * @return
     * @throws Exception
     *
     * 返回值说明:
     *      boolean   false 表示拦截 一般配合重定向方式使用
     *
     * 业务调用:
     *      1.获取cookie中的数据
     *      2.检查redis中是否有数据
     *      3.校验用户是否登录.
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.获取cookie中的数据,检查是否登录
        String ticket = CookieUtil.getCookieValue(request, "JT_TICKET");
        if(StringUtils.hasLength(ticket) && jedisCluster.exists(ticket)){//判断数据是否有值
                //2.动态获取user信息
                String json = jedisCluster.get(ticket);
                //3.将json转化为用户对象
                User user = ObjectMapperUtil.toObj(json, User.class);
                request.setAttribute("JT_USER", user);
                return true;    //表示程序放行
        }

        //实现用户重定向
        response.sendRedirect("/user/login.html");
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

        request.removeAttribute("JT_USER");
    }
}

2.2.5 编辑CartController在这里插入图片描述

2.3 ThreadLocal

2.3.1 ThreadLocal作用

名称: 本地线程变量
作用: 在同一个线程内,实现数据共享.
在这里插入图片描述

2.3.2 封装工具API

package com.jt.util;

import com.jt.pojo.User;

public class UserThreadLocal {
    //线程的一个属性  ThreadLocal是线程安全的
    private static ThreadLocal<User> threadLocal = new ThreadLocal<>();

    public static void set(User user){
        threadLocal.set(user);
    }

    public static User get(){

        return threadLocal.get();
    }

    public static void remove(){

        threadLocal.remove();   //删除数据
    }
}

2.3.3 基于ThreadLocal实现数据取赋值操作

1.拦截器赋值
在这里插入图片描述

2.用户取值
在这里插入图片描述

3.数据销毁
在这里插入图片描述

3.订单模块

3.1 订单确认页面跳转

3.1.1 业务分析

说明: 当点击去结算按钮时,应该跳转到订单确认页面order-cart.jsp.
在这里插入图片描述

3.1.2 编辑OrderController

package com.jt.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.jt.pojo.Cart;
import com.jt.service.DubboCartService;
import com.jt.util.UserThreadLocal;
import org.springframework.beans.factory.annotation.Autowired;
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
    private DubboCartService cartService;

    /**
     * 业务说明:
     *      当点击按钮时,跳转到订单确认页面  cartList购物车数据
     * URL地址:http://www.jt.com/order/create.html
     * 参数:  userId
     * 返回值: 页面逻辑名称 order-cart
     * 页面取值: ${carts}
     */
    @RequestMapping("/create")
    public String orderCreate(Model model){

        long userId = UserThreadLocal.get().getId();
        List<Cart> cartList = cartService.findCartListByUserId(userId);
        model.addAttribute("carts",cartList);
        return "order-cart";
    }





}

3.1.3 页面效果展现

在这里插入图片描述

3.2 订单项目创建

3.2.1 创建订单项目

在这里插入图片描述

3.2.2 添加继承/依赖/插件

 <dependencies>
        <dependency>
            <groupId>com.jt</groupId>
            <artifactId>jt-common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <!--添加插件 有main方法时 需要添加插件-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

3.2.3 关于订单表设计说明

在这里插入图片描述

3.2.4 编辑POJO

在这里插入图片描述

3.2.5 代码结构如下

在这里插入图片描述

3.3 SpringMVC 参数传递方式

3.3.1 为简单参数赋值

<input  type="text" name="username"  value="admin" />

	public void addUser(String username){
	}

3.3.2 为对象赋值

<input  type="text" name="id"  value="100" />
<input  type="text" name="username"  value="admin" />
<input  type="text" name="age"  value="18" />

public void addUser(User user){
}

3.3.3 为对象引入赋值

问题: 有时可能遇到重名属性! 如何处理?

<input  type="text" name="name"  value="二郎神" />
	<input  type="text" name="age"  value="30" />
	<input  type="text" name="dog.name"  value="啸天犬" />
	<-- 为list集合赋值   -->
	<input  type="text" name="hobbys[0]"  value="敲代码" />
//利用对象的方式进行封装
public class User {
	private String name;
	private Integer age;
	private Dog dog;
	private List hobbys
}

public class Dog {
	private String name;
	private Integer age;
}

//	SpringMVC 参数接收
public void addUser(User user){
}

3.4 订单提交

3.4.1 页面分析

1).页面URL分析
在这里插入图片描述

2).参数说明
在这里插入图片描述

3).POJO对象封装
在这里插入图片描述

4).页面JS分析

jQuery.ajax( {
			type : "POST",
			dataType : "json",
			url : "/order/submit",
			//将name属性与值进行拼接 形式 name=value1&name2=value2&name3=value3......
			//表单序列化,可以简化参数写法
			data : $("#orderForm").serialize(),
			cache : false,
			success : function(result) {    //SysResult对象
				if(result.status == 200){   //要求返回orderId
					location.href = "/order/success.html?id="+result.data;
				}else{
					$("#submit_message").html("订单提交失败,请稍后重试...").show();
				}
			},
			error : function(error) {
				$("#submit_message").html("亲爱的用户请不要频繁点击, 请稍后重试...").show();
			}
		});

3.4.2 编辑OrderController

/**
     * 实现订单入库操作
     * url分析:   http://www.jt.com/order/submit
     * 参数:      整个form表单 Order对象
     * 返回值:    SysResult对象
     * 页面取值:  要求返回orderId
     */
    @RequestMapping("/submit")
    @ResponseBody
    public SysResult submit(Order order){
        long userId = UserThreadLocal.get().getId();
        order.setUserId(userId);
        String orderId = orderService.saveOrder(order);
        //完成订单之后,应该删除购物车.. 分布式事务....
        //cartService.deleteCart();
        return SysResult.success(orderId);
    }

3.4.3 编辑OrderService

package com.jt.service;

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

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.dubbo.config.annotation.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
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;

@Service
public class OrderServiceImpl implements DubboOrderService {
	
	@Autowired
	private OrderMapper orderMapper;
	@Autowired
	private OrderShippingMapper orderShippingMapper;
	@Autowired
	private OrderItemMapper orderItemMapper;

	/**
	 * 完成3张表入库操作
	 * order表入库
	 * orderItem表入库
	 * OrderShipping表入库
	 * 动态生成orderId.设定默认状态
	 * 注意数据库事务控制
	 * @param order
	 * @return
	 */
	@Override
	@Transactional
	public String saveOrder(Order order) {
		//动态生成主键
		String orderId = "" + order.getUserId() + System.currentTimeMillis();
		//1.完成订单入库操作
		order.setOrderId(orderId).setStatus(1);
		orderMapper.insert(order);
		System.out.println("订单入库操作成功!!!");

		//2.完成订单物流入库
		OrderShipping orderShipping = order.getOrderShipping();
		orderShipping.setOrderId(orderId);
		orderShippingMapper.insert(orderShipping);
		System.out.println("订单物流入库成功!!!");

		//3.完成订单商品入库操作
		List<OrderItem> orderItems = order.getOrderItems();
		for (OrderItem orderItem : orderItems){
			orderItem.setOrderId(orderId);
			orderItemMapper.insert(orderItem);
		}
		System.out.println("订单全部入库成功!!!!");
		return orderId;
	}
}

3.5 订单查询

3.5.1 业务分析

说明: 当用户订单入库之后,应该跳转到订单的成功页面. 格式如下:
页面数据: ${order}

在这里插入图片描述
在这里插入图片描述

3.5.2 编辑OrderController

/**
     * 实现订单查询
     * url: http://www.jt.com/order/success.html?id=71613981329562
     * 参数: orderId
     * 返回值: 成功页面 success.jsp
     * 页面取值: Order对象(包含其它2个业务数据) ${order.orderId}
     */
    @RequestMapping("/success")
    public String success(String id,Model model){
        //根据id 查询订单对象
        Order order = orderService.findOrderById(id);
        model.addAttribute("order", order);
        return "success";
    }

3.5.3 编辑OrderService

@Override
	public Order findOrderById(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);
		return order.setOrderShipping(orderShipping).setOrderItems(orderItems);
	}

3.5.4 页面效果
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值