【SpringBoot商城秒杀系统项目实战14】秒杀功能的实现(秒杀业务逻辑处理)

先去设置数据库里面的秒杀时间
假设当前时间是2019-05-28 19:30:12
1.已经开始
2.秒杀结束
3.秒杀倒计时
在这里插入图片描述
所以我们去秒杀第一个商品:
在这里插入图片描述
在之前的goods_detail.html里面的秒杀按钮点击之后提交/miaosha/do_miaosha,以POST类型提交,带有数据是秒杀商品的goodsId

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

MiaoshaController代码:

	@RequestMapping("/miaosha")
	@Controller
	public class MiaoshaController{
	@Autowired
	GoodsService goodsService;
	@Autowired
	RedisService redisService;
	@Autowired
	MiaoshaService miaoshaService;
	@Autowired
	OrderService 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个线程,那么库存就会-10
			model.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 {
	@Autowired
	GoodsService goodsService;
	@Autowired
	OrderService orderService;
	/**
	 * 秒杀,原子操作:1.库存减1,2.下订单,3.写入秒杀订单--->是一个事务
	 * 返回生成的订单
	 * @param user
	 * @param goodsvo
	 * @return
	 */
	@Transactional
	public OrderInfo miaosha(MiaoshaUser user, GoodsVo goodsvo) {
		//1.减少库存,即更新库存
		goodsService.reduceStock(goodsvo);//考虑减少库存失败的时候,不进行写入订单
		//2.下订单,其中有两个订单: order_info   miaosha_order
		OrderInfo orderinfo=orderService.createOrder(user,goodsvo);
		return orderinfo;
	}	
	}
	

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

秒杀订单表miaosha_order:
在这里插入图片描述
为秒杀订单表添加唯一索引:
在这里插入图片描述
OrderService 代码:

	@Service
	public class OrderService {
	@Autowired
	OrderDao 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
	 */
	@Transactional
	public OrderInfo createOrder(MiaoshaUser user, GoodsVo goodsvo) {
		//1.生成order_info
		OrderInfo orderInfo=new OrderInfo();
		orderInfo.setDeliveryAddrId(0L);//long类型 private Long deliveryAddrId;   L
		orderInfo.setCreateDate(new Date());
		orderInfo.setGoodsCount(1);
		orderInfo.setGoodsId(goodsvo.getId());
		//秒杀价格
		orderInfo.setGoodsPrice(goodsvo.getMiaoshaPrice());
		orderInfo.setOrderChannel(1);
		//订单状态  ---0-新建未支付  1-已支付  2-已发货  3-已收货
		orderInfo.setOrderStatus(0);
		//用户id
		orderInfo.setUserId(user.getId());
		//返回orderId
		//long orderId=
		orderDao.insert(orderInfo);
		//2.生成miaosha_order
		MiaoshaOrder miaoshaorder =new MiaoshaOrder();
		miaoshaorder.setGoodsId(goodsvo.getId());
		//将订单id传给秒杀订单里面的订单orderid
		miaoshaorder.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);    
	
}
基于SpringBoot+SpringMVC,+Mybatis的电商秒杀购物项目源码.zip # 秒杀商城系统设计 ## 1. 产品概述 秒杀是伴随着电子商务流行以来就有的一种营销模式,直白理解就是卖家以限定数量,或者限定时间,以极低的价格吸引大量的消费者关注,带动店铺整体发展的一种营销手法。由于商品价格低廉,往往一上架就被抢购一空,有时甚至只用几秒钟。 我完整地设计并实现秒杀商城原型系统,包含三大部分:秒杀商城商城管理系统和高并发秒杀业务。 ##### 1.1 **秒杀商城** 秒杀商城是是本项目的主要部分,实现了完整的业务流程,包括用户登录、用户注册、商品列表、商品详情浏览、购物车、查看订单、用户下单、秒杀业务等功能。这些功能会在报告的最后展示。 ##### 1.2 **管理系统** 考虑到系统设计的完整性,除了普通用户之外,还应有系统管理员,这里因为我们是B2C的业务,其中B可以认为是使用管理系统的人。其中管理系统包含了管理员注册、管理员登录、创建商品、商品管理(上架或下架)、用户管理(禁用或解禁)、订单管理(是否执行订单)。这些功能会在报告的最后展示。 ##### 1.3 **高并发秒杀业务** 通过对网络吞吐量(TPS)进行直观的表现服务器对于并发量得性能提升,使用Redis技术、多级Cache缓存技术等技术对后端进行了优化,使得服务器并发处理的性能得到了几倍得性能提升。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员小台

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值