分布式商城购物车实现

版权声明:个人收集,转载注明,谢谢支持 https://blog.csdn.net/qq_42629110/article/details/84840064

完成购物工程和订单工程

购物工程流程

购物车添加

业务方法

@Override
public String addCart(Cart cart, User user, String cartToken) {
    //是否登录进行不同的处理
    if(user == null){//没有用户登录,数据放到redis缓存中
        if(cartToken == null){
            //第一次添加购物车创建uuid
            cartToken = UUID.randomUUID().toString();
        }
        //把数据放在redis中
        redisTemplate.opsForList().leftPush(cartToken, cart);
        //设置失效时间
        redisTemplate.expire(cartToken, 365, TimeUnit.DAYS);
    }else{//用户登录直接调动Dao放到数据库中
        cart.setUid(user.getId());
        cartDao.addCart(cart);
    }
    //第一次添加购物车将令牌返回
    return cartToken;
}

购物车信息的存到Cookie中

@SystemLogAnno(info = "添加商品到购物车",logType = 3)
@IsLogin//默认不需要强制登录
@RequestMapping("/addCart")
public String addCart(@CookieValue(value = Constant.CART_TOKEN,required = false) String cartToken,
        Cart cart,User user,
        HttpServletResponse response){
    cartToken = cartService.addCart(cart, user, cartToken);
    //如果不为空则是第一次登陆,即Service有返回值
    if(cartToken != null){
        Cookie cookie = new Cookie(Constant.CART_TOKEN, cartToken);
        cookie.setPath("/");
        cookie.setMaxAge(60 * 60 * 24 * 365);
        response.addCookie(cookie);
    }
    return "success";
}

购物车信息的展示

获得购物车信息

@Override
public List<Cart> cartList(String cartToken, User user) {
    List<Cart> carts = null;
    //如果没有登录就去缓存中查
    //为了合并购物车不论有没有登录我都先去缓存中查一遍
    if(cartToken != null){
        Long size = redisTemplate.opsForList().size(cartToken);
        carts = redisTemplate.opsForList().range(cartToken, 0, size);
        //因为缓存中的购物车是没有商品其他信息的,需要在数据库中再查找商品的信息,放到carts中
        for (int i = 0; i < carts.size(); i++) {
            GoodsInfo goodsInfo = goodsInfoDao.queryGoodsInfoById(carts.get(i).getGid());
            carts.get(i).setGoodsInfo(goodsInfo);
        }
    }
    //在判断是否已经登录
    if(user != null){
        //已经登录,缓存中可能还有数据
        //此时已经登陆了,将缓存中的数据放到数据库中
        if(carts != null ){
            for (int i = 0; i < carts.size(); i++) {
                carts.get(i).setUid(user.getId());
                cartDao.addCart(carts.get(i));
            }
        }
        //合并后清空缓存中的数据
        redisTemplate.delete(cartToken);
        //再去数据库中查询
        carts = cartDao.queryByUid(user.getId());
    }
    return carts;
}

1.首页工程使用json发送请求展示缩略图

/**
 * jsonp+redis+cookie实现购物缩略图展示
 * @param cartToken
 * @param user
 * @return
 */
@SystemLogAnno(info = "jsonp查看购物车数据",logType = 6)
@IsLogin//默认不需要强制登录
@RequestMapping("/cartList")
@ResponseBody
public String cartList(@CookieValue(value = Constant.CART_TOKEN,required = false) String cartToken,
                       User user){
    //直接调用业务层获得数据
    List<Cart> carts = cartService.cartList(cartToken, user);
    return "cartList(" + new Gson().toJson(carts) + ")";
}

2.购物车页面

//此时用户依旧可以使游客状态,一旦用户需要进入订单模块,必须强制登陆
@SystemLogAnno(info = "跳转到购物车页面查看购物车数据",logType = 7)
@IsLogin//默认不需要强制登录
@RequestMapping("/showCartList")
public String showCartList(@CookieValue(value = Constant.CART_TOKEN,required = false) String cartToken,
                       User user, Model model){
    //直接调用业务层获得数据
    List<Cart> carts = cartService.cartList(cartToken, user);
    model.addAttribute("carts",carts);
    return "cartList";
}

3.购物车页面设计
用户可以对购物车列表进行CRUD包括数量的修改,对于数量的修改,我们可以设计为点击事件每一次点击都发送一个异步请求修改数据库中的值,并且刷新页面数据

订单工程流程

订单编辑页面

分析:
订单编辑页面所需的数据:
1.用户id->通过id获取用户的地址信息
2.选择的商品信息以及商品数量也就是我们的购物车对象,将其当作一个表单提交
业务方法:

@RequestMapping("/editOrder")
@IsLogin(true)
public String editOrder(
       //此时可能是从购物车页面强制跳转到登陆页面,需要先将购物车添加到数据库中
       @CookieValue(value = Constant.CART_TOKEN,required = false) String token,
       Integer[] gid,
       User user,
       Model model){
   //首先要查到当前用户的收货地址
   List<Address> addressList = null;
   if(user != null){
       addressList = addressService.queryAddressByUid(user.getId());
   }

   //总计
   double sumPrice = 0.0;

   //当前用户的购物车
   List<Cart> cartList = cartService.cartList(token, user);
   //用户所需要结算的购物车
   List<Cart> realCartList = new ArrayList<>();
   for (Cart cart : cartList) {
       for (Integer id : gid) {
           if(cart.getGoodsInfo().getId() == id){
               sumPrice += cart.getMoney();
               realCartList.add(cart);
           }
       }
   }

   model.addAttribute("addressList",addressList);
   model.addAttribute("cartList",realCartList);
   model.addAttribute("sumPrice",sumPrice);
   return "orderedit";
}

实现地址新增功能

问题:
1.新增了一个地址需要选择是否是默认地址,如果选择了是默认地址,需要在新增时同时将数据库中默认地址设置为0,我们此处使用存储过程来实现该操作
2.存储过程的事务的控制:
可以在两处地方实现事务控制,1.业务层中添加@Transaction注解即可,2.存储过程中手动开启事务和提交事务,抓取SQLException进行事务的回滚,但是此处一旦进行了控制,我们会发现程序中我们无法捕获异常

存储过程

delimiter &&
create PROCEDURE insertaddress(in p_person VARCHAR(20),in p_phone VARCHAR(20),in p_address VARCHAR(100),in p_uid int,in p_isdefault int)
BEGIN
    if p_isdefault = 1 THEN
        update t_address set isdefault = 0 where isdefault = 1 and uid = p_uid;
    END IF;
        insert into t_address values(null,p_person,p_phone,p_address,p_uid,p_isdefault);
END &&
delimiter ;

控制层

@RequestMapping("/addAddress")
@ResponseBody
@IsLogin(true)
public Integer addAddress(Address address,User user){
    if(user != null){
        address.setUid(user.getId());
    }
    return addressService.insertAddress(address);
}

页面

<form id="formid" method="post">
</form>
<script>
  //添加收货地址
  function addaddress(){
      $.ajax({
          url:"/order/addAddress",
          //将表单数据序列化作为参数传到后台
          data: $("#formid").serialize(),
          success:function(data){
              if(data == 1){
                  //刷新页面
                  location.reload();
              } else {
                  alert("地址添加失败!!!!");
              }
          }
      });
  }
</script>

去支付后,添加订单和订单详情(必须使用事务控制)

1.添加订单
2.添加订单详情
3.删除购物车

控制层

@RequestMapping("/addOrder")
@ResponseBody
@IsLogin(true)
public String addOrder(Integer[] cids,Integer aid,User user){
    //System.out.println(Arrays.toString(cids) + "   " + aid);
    //添加订单和订单详情
    if(user != null){
        return orderService.addOrder(cids,aid,user);
    }
    return null;
}

启动方法上添加事务管理器注册:

@EnableTransactionManagement

业务层

@Override
@Transactional
public String addOrder(Integer[] cids, Integer aid, User user) {
   Orders order = new Orders();

   //查询地址
   Address address = addressDao.queryAddressById(aid);
   //随机订单id
   String orderid = UUID.randomUUID().toString().replace("-","").trim();
   //封装信息
   order.setAddress(address.getAddress());
   order.setPerson(address.getPerson());
   //计算总金额
   double sumPrice = 0;

   List<Cart> cartList = cartDao.queryByIds(cids);

   if(cartList != null && !cartList.isEmpty()){
       for (Cart cart : cartList) {
           sumPrice += cart.getMoney();
       }
   }
   
   order.setOprice(sumPrice);
   order.setOrdertime(new Date());
   order.setOrderid(orderid);
   order.setPhone(address.getPhone());
   //默认状态为0,未支付
   order.setStatus(0);
   order.setUid(user.getId());
   //添加订单,主键回填,下面的订单详情需要设置订单id
   orderDao.addOrder(order);
   //有几个购物车对象就有几条订单详情记录
   List<OrderDetail> orderDetailList = new ArrayList<>();
   for (Cart cart : cartList) {
       //订单详情
       OrderDetail orderDetail = new OrderDetail();
       //封装
       orderDetail.setGcount(cart.getGcount());
       orderDetail.setGid(cart.getGid());
       orderDetail.setGimage(cart.getGoodsInfo().getGoodsPic());
       orderDetail.setGinfo(cart.getGoodsInfo().getGoodsDescription());
       //主键回填后
       orderDetail.setOid(order.getId());
       orderDetail.setPrice(cart.getMoney());
       orderDetail.setGname(cart.getGoodsInfo().getGoodsName());
	   //封装后放到集合中
       orderDetailList.add(orderDetail);
   }
   //必须判断集合是不是为空,否则语法错误
   if(orderDetailList!= null && !orderDetailList.isEmpty()){
       orderDao.addOrderDetails(orderDetailList);
   }
   //订单一旦生成,购物车中的数据需要删除,删除购物车
   cartDao.deleteCarts(cids);
   //订单页面需要使用到订单id
   return order.getOrderid();
}

订单展示

//通过uid查询其订单信息即可
@RequestMapping("/list")
@IsLogin(true)
public String orderList(User user, Model model){
    List<Orders> orders = orderService.queryByUid(user.getId());
    model.addAttribute("orders", orders);
    return "orderlist";
}

猜你喜欢

转载自blog.csdn.net/qq_42629110/article/details/84840064