05、SpringCloud -- 秒杀按钮、秒杀请求流程(各种请求到后台的判断、减库存、下单数据和次数保存)

秒杀按钮

需求:点击抢购的按钮,在未规定的时间段内不可点击
在这里插入图片描述

代码实现:

vue的JS实现:

在vue的js中 , prop 是父组件用来传递数据的一个自定义属性

在这里插入图片描述

秒杀请求

需求:

点击立即秒杀后,从前端发送请求到后端接受的一系列判断

代码

前端

携带数据发送到后端
在这里插入图片描述

后端

Seckill-api
domain

添加两个实体类,秒杀订单信息类和订单详情信息类

在这里插入图片描述

Seckill-server
WebConfig

把自定义参数解析器的配置类拷贝一份到秒杀服务里面。
在这里插入图片描述

1、秒杀请求判断
controller

开始对秒杀的操作进行一系列的判断:是否登录、数据库是否有该商品id、后端再次判断秒杀时间是否已经开始
在这里插入图片描述

2、重复下单判断

判断用户是否重复下单,如果重复下单,提醒不要重复下单

Mapper

先写个Mapper,写数据库查询是否重复下单的语句
在这里插入图片描述

Service 接口

在这里插入图片描述

Impl 实现类

在这里插入图片描述

controller

在这里插入图片描述

3、库存判断

判断是否有库存,如果没有提醒库存不足
在这里插入图片描述

4、秒杀涉及到的操作
_01、减库存

重新建一个秒杀用的service业务层来做秒杀的业务逻辑判断,秒杀的数据会放在t_order_info 订单信息表里面

在这里插入图片描述

创建一个service接口,专门用来处理秒杀订单信息的业务逻辑

在这里插入图片描述
SeckillOrderInfoServiceImpl

在实现里面,因为减库存是减 t_seckill-goods 表的数据,所以得把减库存的实际业务逻辑写在ISeckillGoodService接口那边

在这里插入图片描述

ISeckillGoodService接口,写减库存的实际业务逻辑方法的接口

在这里插入图片描述

impl
在这里插入图片描述

mapper
在这里插入图片描述

_02、创建订单对象并保存

创建出来订单信息保存到数据库中
impl

orderNo订单编号生成使用雪花算法,需要引入一个工具类类

在这里插入图片描述

mapper
写sql把订单信息对象存到数据库表 t_order_info 里面

在这里插入图片描述

_03、用户下单次数数据存储

往 t_seckill_order 表插入一条数据作为这个用户已经下单的依据

因为t_seckill_order 只存用户的id和秒杀的id和订单编号,是用来看用户是否存在重复下单的现象,所以业务逻辑要单独写在ISeckillOrderService接口里面

在这里插入图片描述

mapper
写sql
在这里插入图片描述

出现的问题:

1、sql的update和insert的 括号要写好,具体看sql语句拼接的时候是否正常,会不会关键字和字段拼接在一起

2、秒杀的方法记得加事务注解
在这里插入图片描述
3、seckill-server 服务因为有用到redis,所以需要在yml配置把redis-server的配置加上,这样在项目启动的时候去gitee上面拉数据的话,就不会报错了
在这里插入图片描述

4、远程调用出现繁忙

出现原因:点击立即秒杀多次后,出现了这个【远程调用商品服务繁忙】的问题。

在这里插入图片描述

解决:后面重启,然后gitee密码修改了一下,因为显示在湛江被登录了,但是应该不是解决方法,只是记录一下

5、前端用ajax调用方法,但是后台返回数据的时候,没有走这个seccess的判断,成功和失败都没有弹窗和提示

在这里插入图片描述
解决:这里的success 我写成 seccess,写错了,u写成e,然后就不走那里function函数。

现在就会提示了

失败也会提示了

在这里插入图片描述

成功也能正常跳转页面
在这里插入图片描述

订单编号生成使用雪花算法的代码

package cn.ljh.shop.cloud.util;

/**
 * twitter 的分布式环境全局唯一id算法   雪花算法
 */
public class IdGenerateUtil {
    private long workerId;
    private long datacenterId;
    private long sequence = 0L;
    private long twepoch            = 1288834974657L;
    private long workerIdBits       = 5L;
    private long datacenterIdBits   = 5L;
    private long maxWorkerId        = -1L ^ (-1L << workerIdBits);
    private long maxDatacenterId    = -1L ^ (-1L << datacenterIdBits);
    private long sequenceBits       = 12L;
    private long workerIdShift      = sequenceBits;
    private long datacenterIdShift  = sequenceBits + workerIdBits;
    private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
    private long sequenceMask       = -1L ^ (-1L << sequenceBits); //4095
    private long lastTimestamp      = -1L;

    private static class IdGenHolder {
        private static final IdGenerateUtil instance = new IdGenerateUtil();
    }

    public static IdGenerateUtil get() {
        return IdGenHolder.instance;
    }

    public IdGenerateUtil() {
        this(0L, 0L);
    }

    public IdGenerateUtil(long workerId, long datacenterId) {
        if (workerId > maxWorkerId || workerId < 0) {
            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
        }
        if (datacenterId > maxDatacenterId || datacenterId < 0) {
            throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
        }
        this.workerId = workerId;
        this.datacenterId = datacenterId;
    }

    public synchronized long nextId() {
        long timestamp = timeGen();
        if (timestamp < lastTimestamp) {
            throw new RuntimeException(String.format(
                    "Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
        }
        //如果上次生成时间和当前时间相同,在同一毫秒内
        if (lastTimestamp == timestamp) {
            sequence = (sequence + 1) & sequenceMask;
            if (sequence == 0) {
                timestamp = tilNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0L;
        }
        lastTimestamp = timestamp;
        return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift)
                | (workerId << workerIdShift) | sequence;
    }

    protected long tilNextMillis(long lastTimestamp) {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = timeGen();
        }
        return timestamp;
    }

    protected long timeGen() {
        return System.currentTimeMillis();
    }


}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

_L_J_H_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值