假设当前时间是2020-05-07 16:21:34

  1. 已经开始
  2. 秒杀结束
  3. 秒杀倒计时

所以我们去秒杀第一个商品:

在之前的goods_detail.html里面的秒杀按钮点击之后提交/miaosha/do_miaosha,以POST类型提交,带有数据是秒杀商品的goodsId

新建一个MiaoshaController,定义接收该秒杀请求的接口方法doMiaosha
我们秒杀成功之后,那么会直接进入订单的详情页,所以我们秒杀成功后直接返回订单信息,并且返回值订单页面。

MiaoshaController代码

 @RequestMapping("/miaosha")@Controllerpublic class MiaoshaController{@AutowiredGoodsService goodsService;@AutowiredRedisService redisService;@AutowiredMiaoshaService miaoshaService;@AutowiredOrderService orderService;@RequestMapping("/do_miaosha")public String toList(Model model,MiaoshaUser user,@RequestParam("goodsId") Long goodsId) {model.addAttribute("user", user);//如果用户为空,则返回至登录页面if(user==null){return "login";}GoodsVo goodsvo=goodsService.getGoodsVoByGoodsId(goodsId);//判断商品库存,库存大于0,才进行操作,多线程下会出错int  stockcount=goodsvo.getStockCount();      if(stockcount<=0) {//失败         库存至临界值1的时候,此时刚好来了加入10个线程,那么库存就会-10model.addAttribute("errorMessage", CodeMsg.MIAOSHA_OVER_ERROR);return "miaosha_fail";}//判断这个秒杀订单形成没有,判断是否已经秒杀到了,避免一个账户秒杀多个商品 MiaoshaOrder order=orderService.getMiaoshaOrderByUserIdAndGoodsId(user.getId(),goodsId);if(order!=null) {//重复下单model.addAttribute("errorMessage", CodeMsg.REPEATE_MIAOSHA);return "miaosha_fail";}//可以秒杀,原子操作:1.库存减1,2.下订单,3.写入秒杀订单--->是一个事务OrderInfo orderinfo=miaoshaService.miaosha(user,goodsvo);//如果秒杀成功,直接跳转到订单详情页上去。model.addAttribute("orderinfo", orderinfo);model.addAttribute("goods", goodsvo);return "order_detail";//返回页面login}
}

秒杀业务主要逻辑:

判断登录
根据商品id从数据库拿到商品
判断库存,库存足够,进行秒杀,不足则结束
判断是否重复秒杀(我们限制一个用户只能秒杀一件商品,怎么判断?即从数据库根据商品和用户id 查询秒杀订单表,如果已经存在订单,说明重复秒杀 ,给出提示,退出)
以上都通过,那么该用户可以秒杀商品
注意:
执行秒杀逻辑是一个原子操作,是一个事务:

库存减1
下订单(写入秒杀订单)
所以使用@Transactional注解标注,其中一步没有成功,则回滚

MiaoshaService 代码:

@Service
public class MiaoshaService {@AutowiredGoodsService goodsService;@AutowiredOrderService orderService;/*** 秒杀,原子操作:1.库存减1,2.下订单,3.写入秒杀订单--->是一个事务* 返回生成的订单* @param user* @param goodsvo* @return*/@Transactionalpublic OrderInfo miaosha(MiaoshaUser user, GoodsVo goodsvo) {//1.减少库存,即更新库存goodsService.reduceStock(goodsvo);//考虑减少库存失败的时候,不进行写入订单//2.下订单,其中有两个订单: order_info   miaosha_orderOrderInfo orderinfo=orderService.createOrder(user,goodsvo);return orderinfo;}
}

注意:执行秒杀事务的时候,先生成详细订单,然后生成秒杀订单,为了进一步确保秒杀过程中一个用户只能秒杀一件商品,我们给秒杀订单表miaosha_order表添加一个唯一索引,如果再次插入相同的id与goodsId相同的字段,那么将不会被允许,从而在事务中插入失败而回退。

秒杀订单表miaosha_order:

为秒杀订单表添加唯一索引:

OrderService 代码:

@Service
public class OrderService {@AutowiredOrderDao orderDao;/*** 代码1.0* 根据用户userId和goodsId判断是否有者条订单记录,有则返回此纪录* @param id* @param goodsId* @return*/public MiaoshaOrder getMiaoshaOrderByUserIdAndGoodsId(Long userId, Long goodsId) {return orderDao.getMiaoshaOrderByUserIdAndGoodsId(userId,goodsId);}/*** 生成订单,事务* @param user* @param goodsvo* @return*/@Transactionalpublic OrderInfo createOrder(MiaoshaUser user, GoodsVo goodsvo) {//1.生成order_infoOrderInfo orderInfo=new OrderInfo();orderInfo.setDeliveryAddrId(0L);//long类型 private Long deliveryAddrId;   LorderInfo.setCreateDate(new Date());orderInfo.setGoodsCount(1);orderInfo.setGoodsId(goodsvo.getId());//秒杀价格orderInfo.setGoodsPrice(goodsvo.getMiaoshaPrice());orderInfo.setOrderChannel(1);//订单状态  ---0-新建未支付  1-已支付  2-已发货  3-已收货orderInfo.setOrderStatus(0);//用户idorderInfo.setUserId(user.getId());//返回orderId//long orderId=orderDao.insert(orderInfo);//2.生成miaosha_orderMiaoshaOrder miaoshaorder =new MiaoshaOrder();miaoshaorder.setGoodsId(goodsvo.getId());//将订单id传给秒杀订单里面的订单orderidmiaoshaorder.setOrderId(orderInfo.getId());miaoshaorder.setUserId(user.getId());orderDao.insertMiaoshaOrder(miaoshaorder);return orderInfo;} public OrderInfo getOrderByOrderId(long orderId) {return orderDao.getOrderByOrderId(orderId);}
}

OrderDao代码:

@Mapper
public interface OrderDao {@Select("select * from miaosha_order where user_id=#{userId} and goods_id=#{goodsId}")  public MiaoshaOrder getMiaoshaOrderByUserIdAndGoodsId(@Param("userId")Long userId, @Param("goodsId")Long goodsId);@Insert("insert into order_info (user_id,goods_id,goods_name,goods_count,goods_price,order_channel,order_status,create_date) values "+ "(#{userId},#{goodsId},#{goodsName},#{goodsCount},#{goodsPrice},#{orderChannel},#{orderStatus},#{createDate})")@SelectKey(keyColumn="id",keyProperty="id",resultType=long.class,before=false,statement="select last_insert_id()")public long insert(OrderInfo orderInfo);//使用注解获取返回值,返回上一次插入的id@Select("select * from order_info where user_id=#{userId} and goods_id=#{goodsId}")  public OrderInfo selectorderInfo(@Param("userId")Long userId, @Param("goodsId")Long goodsId);//使用注解获取返回值,返回上一次插入的id@Insert("insert into miaosha_order (user_id,goods_id,order_id) values (#{userId},#{goodsId},#{orderId})")public void insertMiaoshaOrder(MiaoshaOrder miaoshaorder);@Select("select * from order_info where id=#{orderId}")  public OrderInfo getOrderByOrderId(@Param("orderId")long orderId);
}

秒杀系统 秒杀功能实现相关推荐

  1. 00 如何设计一个秒杀系统——秒杀系统架构设计都有哪些关键点

    一.如何理解秒杀系统 秒杀系统其实主要解决两个问题,一个是并发读,一个是并发写.并发读的核心优化理念是尽量减少用户到服务端来"读"数据,或者让他们读更少的数据:并发写的处理原则也一 ...

  2. 【SpringBoot商城秒杀系统秒杀优化学习笔记】

    课程介绍 什么是秒杀 秒杀场景一般会在电商网站举行一些活动或者节假日在12306网站上抢票时遇到.对于电商网站中一些稀缺或者特价商品,电商网站一般会在约定时间点对其进行限量销售,因为这些商品的特殊性, ...

  3. 设计一个秒杀系统-秒杀方案分析

    学习使用,老鸟飞过,欢迎交流 秒杀系统应该考虑哪些因素 高可用:秒杀系统最大的特点就是并发高,在极短的时间内, 瞬间用户量大.试想一下双11的时候可能会有几十万的用户去访问同一个商品详情页面秒杀同一个 ...

  4. 秒杀系统(1)——秒杀功能设计理念

    文章目录 电商系统下单功能概述 订单量:从 0 到 1000(架构1) 订单量:从 1000 到 100万 锁机制 悲观锁 乐观锁 分布式锁 消息队列 消息队列:架构2 从电商系统到秒杀系统 流量限制 ...

  5. 秒杀系统 mysql_秒杀系统-介绍

    秒杀系统 秒杀系统其实是针对库存做的系统.用户成功秒杀商品,对于我们系统的操作就是减库存和记录用户的购买明细.用户的购买明细包括记录谁购买成功.购买成功的时间和付款信息.而对于减库存操作,需要考虑到以 ...

  6. 尚硅谷-谷粒商城-电商项目-秒杀系统-笔记

    商城项目简介 项目主要实现了一个模拟电商的分布式秒杀系统,核心模块包括注册登录模块.订单模块.秒杀模块. 框架是spring一套,用到的组件包Nignx服务器,redis,Mysql数据库,rabbi ...

  7. 打造千万级流量秒杀系统第一课 功能需求:秒杀业务背景及前端需求是怎么产生的?

    你好,我是易乐天,到 2020 年,我在软件行业已经 10 年了. 我曾经做过 Linux 系统编程相关的工作,积累了许多性能优化方面的经验.后来,我开始做分布式系统的架构设计和实现,特别是项目当中涉 ...

  8. 这一次,彻底弄懂“秒杀系统”

    " 说到"秒杀",恐怕大多数人想到的就是"双 11","促销","买买买"等火爆的场面吧. 图片来自 Pexe ...

  9. 打造千万级流量系统——秒杀系统(需求篇)

    一.功能需求分析 1.前端需求分析 前端是一个系统中离用户最近的部分,为用户提供信息展示.交互逻辑等.当前端的需求基本决定,一个系统的功能需求也就随之产生. 所以,接下来,我们重点分析一下秒杀系统前端 ...

最新文章

  1. AutoMapper 入门
  2. 开发路上踩过的坑要一个个填起来————持续更新······(7月30日)
  3. 程序间数据共享与传递(3):EXPORT/IMPORT、SAP/ABAP Memory
  4. 直播预告 | 后广告时代数据助力融合媒体用户收入增长
  5. 设计模式:代理模式是什么,Spring AOP还和它有关系?
  6. python36_第36 p,就这几个方法,Python中文件的操作
  7. 实例解析网络编程中的另类内存泄漏
  8. Python数据可视化的四种简易方法 1
  9. 【java学习之路】(java框架)004.Mybatis SQL映射文件详解
  10. Openssl genrsa命令
  11. 软件测试学习资料汇总
  12. 腾讯云安装宝塔面板详细教程
  13. ES6 阮一峰阅读学习
  14. matplotlib 水平堆积图
  15. MATLAB图形句柄
  16. php静态页面制作,ps制作静态的html页面
  17. 有个程序猿很忧桑:一个命令rm -rf/ ,他把整个公司删没了...
  18. linux查找表空间使用情况,表空间的使用情况查询及管理
  19. 配件查询网站用java,基于jsp的配件管理系统-JavaEE实现配件管理系统 - java项目源码...
  20. [小黄书管理平台]Angularjs 2.0应用的国际化

热门文章

  1. zabbix设置中文字体
  2. 算法练习:罗马数字转整数
  3. 阅次元小说推荐-最终成品
  4. 电子商务法律法规【2】
  5. java线程锁有哪几种_java有哪些锁种类
  6. Java的无参构造函数
  7. svn 服务器忽略文件夹,关于构建自动化:SVN checkout忽略文件夹
  8. 二次函数顶点坐标公式的另一种推导
  9. mysql中视图和表的区别及联系,mysql 中视图和表的区别以及联系是什么?
  10. Mysql-高级查询语句