秒杀项目学习笔记-秒杀功能实现

本文详细介绍了一个商品秒杀功能的实现过程,包括前端按钮设计、后端Controller层、Service层及Dao层的具体代码实现,展示了如何处理秒杀请求、检查库存、生成订单以及更新数据库。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目的:商品详情的页面中立即秒杀的功能实现

<td>
    <form id="miaoshaForm" method="post" action="/miaosha/do_miaosha">
        <button class="btn btn-primary btn-block" type="submit" id="buyButton">立即秒杀</button>
        <input type="hidden" name="goodsId" th:value="${goods.id}" />
    </form>
</td>

Controller层

创建MiaoshaController
@Controller
@RequestMapping("/miaosha")
public class MiaoshaController {
    @Autowired
    GoodsService goodsService;
    @Autowired
    OrderService orderService;
    @Autowired
    MiaoshaService miaoshaService;
    
    @RequestMapping("/do_miaosha")
    public String list(Model model, MiaoshaUser user, @RequestParam("goodsId")long goodsId){
        model.addAttribute("user", user);
        //查看登陆状态,未登录返回登陆页面
        if(user == null) {
            return "login";
        }
        //判断库存
        GoodsVo goods = goodsService.getGoodsVoByGoodsId(goodsId);
        int stock = goods.getStockCount();
        if(stock <= 0) {
            model.addAttribute("errmsg", CodeMsg.MIAO_SHA_OVER.getMsg());
            return "miaosha_fail";
        }
        //查询订单,判断是否已经秒杀到了
        MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(),goodsId);
        if(order != null){
            model.addAttribute("errmsg", CodeMsg.REPEATE_MIAOSHA.getMsg());
            return "miaosha_fail";
        }
        //减少库存,生成订单
        OrderInfo orderInfo = miaoshaService.miaosha(user, goods);
        model.addAttribute("orderInfo", orderInfo);
        model.addAttribute("goods", goods);
        return "order_detail";//返回订单详情页
    }
}

Service层

创建OrderService

OrderService会生成两个表:OrderInfo、MiaoshaOrder。

@Service
public class OrderService {
    @Autowired
    OrderDao orderDao;
    public MiaoshaOrder getMiaoshaOrderByUserIdGoodsId(long userId, long goodsId) {
        return orderDao.getMiaoshaOrderByUserIdGoodsId(userId, goodsId);
    }
    @Transactional
    public OrderInfo createOrder(MiaoshaUser user, GoodsVo goods) {
        //生成orderInfo对象并赋值,插入到order_info表
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setCreateDate(new Date());
        orderInfo.setDeliveryAddrId(0L);
        orderInfo.setGoodsCount(1);
        orderInfo.setGoodsId(goods.getId());
        orderInfo.setGoodsName(goods.getGoodsName());
        orderInfo.setGoodsPrice(goods.getMiaoshaPrice());
        orderInfo.setOrderChannel(1);
        orderInfo.setStatus(0);
        orderInfo.setUserId(user.getId());
        long orderId = orderDao.insert(orderInfo);
        //生成miaoshaOrder对象并赋值,插入到miaosha_order表中
        MiaoshaOrder miaoshaOrder = new MiaoshaOrder();
        miaoshaOrder.setGoodsId(goods.getId());
        miaoshaOrder.setOrderId(orderId);
        miaoshaOrder.setUserId(user.getId());
        orderDao.insertMiaoshaOrder(miaoshaOrder);
        return orderInfo;
    }
}
创建MiaoshaService

调用goodsService将商品数量减一,调用orderService生成两个订单表
在MiaoshaService下不建议使用orderDao、goodsDao,可以使用OrderService、GoodsService完成相应功能。因为调用service有可能

@Service
public class MiaoshaService {
    @Autowired
    OrderService orderService;
    @Autowired
    GoodsService goodsService;
    @Transactional
    public OrderInfo miaosha(MiaoshaUser user, GoodsVo goods){
        //减库存 下订单 写入秒杀订单
        //将miaosha_goods里面对应商品的数量减一
        goodsService.reduceStock(goods);
        //生成两张表:order_info maiosha_order 并且返回order_info
        return orderService.createOrder(user, goods);
    }
}
GoodsService添加如下方法

只需要传goods.id,让goodsDao把相应商品的数量减一。

 public void reduceStock(GoodsVo goods){  
        goodsDao.reduceStock(goods.getId());
    }

Dao层

GoodsDao添加如下方法
@Update("update miaosha_goods set stock_count = stock_count - 1 where goods_id = #{id}")
    public  int reduceStock(long id);
创建OrderDao
@Mapper
public interface OrderDao {

    @Select("select * from miaosha_order where user_id = #{userId} and goods_id = #{goodsId}")
    public MiaoshaOrder getMiaoshaOrderByUserIdGoodsId(@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, status, create_date)values("
            + "#{userId}, #{goodsId}, #{goodsName}, #{goodsCount}, #{goodsPrice}, #{orderChannel},#{status},#{createDate} )")
    @SelectKey(keyColumn="id", keyProperty="id", resultType=long.class, before=false, statement="select last_insert_id()")
    public long insert(OrderInfo orderInfo);

    @Insert("insert into miaosha_order (user_id, goods_id, order_id)values(#{userId}, #{goodsId}, #{orderId})")
    public int insertMiaoshaOrder(MiaoshaOrder miaoshaOrder);
}

效果

order_detail.html,只显示秒杀商品的名称
order_detail.html
在这里插入图片描述
原来秒杀商品数量都是8个,现在iphonex少了一个
在这里插入图片描述

慕课网Java高并发秒杀(课程) 很好的spring,springMVC,mybatis,bootstrap,jQuery,mysql,Restful学习案例 SQL脚本 CREATE DATABASE seckill; USE seckill; -- todo:mysql Ver 5.7.12for Linux(x86_64)中一个表只能有一个TIMESTAMP CREATE TABLE seckill( `seckill_id` BIGINT NOT NUll AUTO_INCREMENT COMMENT '商品库存ID', `name` VARCHAR(120) NOT NULL COMMENT '商品名称', `number` int NOT NULL COMMENT '库存数量', `start_time` TIMESTAMP NOT NULL COMMENT '秒杀开始时间', `end_time` DATETIME NOT NULL COMMENT '秒杀结束时间', `create_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (seckill_id), key idx_start_time(start_time), key idx_end_time(end_time), key idx_create_time(create_time) )ENGINE=INNODB AUTO_INCREMENT=1000 DEFAULT CHARSET=utf8 COMMENT='秒杀库存表'; -- 初始化数据 INSERT into seckill(name,number,start_time,end_time) VALUES ('3000元秒杀iphone6',100,'2016-01-01 00:00:00','2016-12-31 00:00:00'), ('2000元秒杀ipad',100,'2016-01-01 00:00:00','2016-05-01 00:00:00'), ('6000元秒杀mac book pro',100,'2016-07-01 00:00:00','2016-12-31 00:00:00'), ('7000元秒杀iMac',100,'2016-05-01 00:00:00','2016-12-31 00:00:00') -- 秒杀成功明细表 -- 用户登录认证相关信息(简化为手机号) CREATE TABLE success_killed( `seckill_id` BIGINT NOT NULL COMMENT '秒杀商品ID', `user_phone` BIGINT NOT NULL COMMENT '用户手机号', `state` TINYINT NOT NULL DEFAULT -1 COMMENT '状态标识:-1:无效 0:成功 1:已付款 2:已发货', `create_time` TIMESTAMP NOT NULL COMMENT '创建时间', PRIMARY KEY(seckill_id,user_phone),/*联合主键*/ KEY idx_create_time(create_time) )ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='秒杀成功明细表' SHOW CREATE TABLE seckill\G;#显示表的创建信息 Mybatis两个问题?①sql写在哪里?②怎么实现DAO接口?第一个问题:注解或者XML选择XML.第二个问题:Mapper自动实现DAO接口或者API编程方式实现DAO接口.选择Mapper.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值