秒杀下单功能实现by和奇科技

作者:和奇一号发表于:2019-05-10

构建秒杀的功能模块  web   interface   service

从redis 中获取需要参加秒杀的商品

后台代码:

service层:

@Service
@Transactional
public class SeckillServiceImpl implements SeckillService{
 
    @Autowired
    private RedisTemplate redisTemplate;
    /**
     * 从redis 中查询所有要参加秒杀的商品
     * @return
     */
    @Override
    public List<TbSeckillGoods> findAllSeckillGoodsFromRedis() {
        //获取redis中的数据
        List seckill_goods = redisTemplate.boundHashOps("SECKILL_GOODS").values();
        return seckill_goods;
    }
}
---------------------

interface层和controller层:

/**
     * 从redis中查询所有的秒杀商品列表
     */
    public List<TbSeckillGoods> findAllSeckillGoodsFromRedis();
 
//controller层:
@RestController
@RequestMapping("/seckill")
public class SeckillController {
 
 
    @Reference
    private SeckillService seckillService;
 
    /**
     * 从redis中查询所有的要参加秒杀的商品
     * @return
     */
    @RequestMapping("/findSeckillList")
    public List<TbSeckillGoods> findSeckillList(){
     return   seckillService.findAllSeckillGoodsFromRedis();
    }
}
---------------------

前台页面的实现:

我们通过$http内置对象发送请求


//服务层
app.service('seckillService',function($http){
 
    //查询需要秒杀的商品列表
    this.findSeckillList=function(){
        return $http.get('seckill/findSeckillList.do');
    }
});
---------------------
 //控制层
app.controller('seckillController' ,function($scope,$controller   ,seckillService){
    
    $controller('baseController',{$scope:$scope});//继承
    //,$location 跨域
    //查询需要从redis中获得需要的秒杀商品数据
    $scope.findSeckillList=function () {
        seckillService.findSeckillList().success(function (response) {
            $scope.seckillList=response;
        })
    }
});    
---------------------

我们通过秒杀页面跳转到秒杀的详情页,通过路由传参

1557471622978085.png


详情页面的展示:

思路:我们通过商品的id查询商品的详情,前台页面进行展示,注意倒计时的处理,我们通过angularjs中$interval  一个内置对象进行设置

后台我们先从spring-sceurity中获得用户登录的信息,然后从redis中获得商品的数据,组装订单,然后在redis的商品库中减去一,保存订单,当库存为零的是时候我们,更新数据库,清除redis中该商品的数据,注意:一定要在秒杀成功后,扣减库存
---------------------
 /**
     * 保存秒杀的订单
     */
    @RequestMapping("/saveSeckillOrder")
    public Result saveSeckillOrder(Long seckillGoodsId){
        try {
            //基于安全获取登录人信息
            String userId = SecurityContextHolder.getContext().getAuthentication().getName();
 
            if(userId.equals("anonymousUser")){
                return  new Result(false,"请下登录,再下单");
            }
 
            seckillService.saveSeckillOrder(seckillGoodsId,userId);
            return new Result(true,"秒杀下单成功");
        } catch (RuntimeException e) {
            e.printStackTrace();
            return new Result(false,e.getMessage());
        }catch (Exception e) {
            e.printStackTrace();
            return new Result(false,"秒杀下单失败");
        }
    }
---------------------
service层:


/**
     * 保存秒杀订单
     * @param seckillGoodsId
     * @param userId
     */
    @Override
    public void saveSeckillOrder(Long seckillGoodsId, String userId) {
 
        //从缓存中获取秒杀商品
        TbSeckillGoods seckillGoods=  (TbSeckillGoods) redisTemplate.boundHashOps("seckill_goods").get(seckillGoodsId);
 
        if(seckillGoods==null || seckillGoods.getStockCount()<=0){
            throw new RuntimeException("商品售完");
        }
 
 
        //组装秒杀订单数据
        TbSeckillOrder seckillOrder = new TbSeckillOrder();
        /*
        tb_seckill_order
      `id` bigint(20) NOT NULL COMMENT '主键',
      `seckill_id` bigint(20) DEFAULT NULL COMMENT '秒杀商品ID',
      `money` decimal(10,2) DEFAULT NULL COMMENT '支付金额',
      `user_id` varchar(50) DEFAULT NULL COMMENT '用户',
      `seller_id` varchar(50) DEFAULT NULL COMMENT '商家',
      `create_time` datetime DEFAULT NULL COMMENT '创建时间',
      `status` varchar(1) DEFAULT NULL COMMENT '状态',
         */
        seckillOrder.setId(idWorker.nextId());
        seckillOrder.setSeckillId(seckillGoodsId);
        seckillOrder.setMoney(seckillGoods.getCostPrice());
        seckillOrder.setUserId(userId);
        seckillOrder.setSellerId(seckillGoods.getSellerId());
        seckillOrder.setCreateTime(new Date());
        seckillOrder.setStatus("1");//未支付
 
        //设置秒杀商品库存减一
        seckillGoods.setStockCount(seckillGoods.getStockCount()-1);
        //保存秒杀订单
        seckillOrderMapper.insert(seckillOrder);
        if(seckillGoods.getStockCount()<=0){
            //商品售完,没有库存后,需要更新数据库中秒杀商品库存数据
            seckillGoodsMapper.updateByPrimaryKey(seckillGoods);
 
            //清除redis中该商品
            redisTemplate.boundHashOps("seckill_goods").delete(seckillGoodsId);
        }
        //秒选下单成功后,扣减库存
        redisTemplate.boundHashOps("seckill_goods").put(seckillGoodsId,seckillGoods);
 
    }
---------------------
前台代码:

//秒杀下单
    this.saveSeckillOrder=function (seckillGoodsId) {
        return $http.get('seckill/saveSeckillOrder.do?seckillGoodsId='+seckillGoodsId)
    }
---------------------

controller层:

//秒杀下单
    $scope.saveSeckillOrder=function () {
        seckillService.saveSeckillOrder($scope.seckillGoodsId).success(function (response) {
            alert(response.message);
        })
    }
---------------------

测试:保存订单成功,