JAVA高并发秒杀系统构建之——Service层
前言:本文章是《JAVA高并发秒杀系统构建之——业务分析和Dao层》下一篇,主要讲解系统Service层业务逻辑的实现。
首先给出SeckillService接口代码
说明一下,exportSeckillUrl这个方法的主要作用:
1、当秒杀活动还没有开始时,用户调用这个方法后,将会返回系统时间和秒杀时间,进而控制秒杀活动开启与结束
2、通过输出随机的秒杀接口地址,避免了用户利用插件或者猜测拼接url等其他方法,在活动未开始之前,访问秒杀地址。
下面给出Exposer类,该类的作用是暴露秒杀接口地址
接下来是最核心的部分,执行秒杀操作
这里的md5,是之前Exposer类中的md5加密信息。因此,我们可以在执行秒杀操作之前,通过检验md5的正确性,来判断是否进行秒杀操作。
返回值为SeckillExecution类,这个类主要记录了秒杀结果的一些信息
另外,这里抛出了三个异常,分别是秒杀异常,重复秒杀异常,秒杀关闭异常,这三个异常均是运行时异常,因为spring事务的回滚机制在异常方面只能对应运行时异常,
下面来实现SeckillService接口,其实现类为SeckillServiceImpl
这里说一下,盐值字符串是为了增加md5的复杂程度,增加md5破解的难度。
首先是最简单的两个方法的实现,这两个方法直接调用seckillDao的源生代码即可,无需多做处理
接下来是MD5加密的方法,依据seckillId(秒杀商品Id),和之前定义的MD5加密盐值,生成MD5加密字符串。DigestUtils是spring原生的加密工具。
接下来是暴露接口地址的方法
主要业务流程
1、判断该秒杀商品是否存在,如果不存在,设置Exposer类中状态(state)为活动未开启,返回暴露接口类(Exposer),告知用户秒杀商品不存在。
2、如果秒杀商品存在,判断秒杀活动是否开启,如果活动未开启,设置Exposer类中状态(state)为活动未开启,返回暴露接口类(Exposer),告知用户秒杀活动开启时间、结束时间。
3、如果秒杀活动开启,先md5加密后,将加密信息与seckillId封装成暴露接口类(Exposer),并设置状态(state)为活动开启,返回暴露接口类(Exposer)
接下来是最核心的部分
这里做一下解释
1、这里的第一步是首先检验用户传过来的md5是否是正确的(按理来说,用户传过来的md5信息,应是由服务器端通过seckillId生成的,用户无法自己生成md5信息),如果用户自行篡改md5,则服务器后台会抛出异常。
2、异常处理顺序中,为了能够有效区分秒杀关闭异常、重复秒杀异常以及秒杀异常之间的不同,所以应将秒杀关闭异常、重复秒杀异常放在所有异常的前面。同时,为了防止库存更新之后,购买行为的插入出现错误(可能是因为数据库断连之类的错误),因此,应将所有编译期异常出现时,抛出运行期异常,目的就是为了让事务回滚,保证数据的正确性。
3、SeckillStatEnum是一个枚举类,主要是封装秒杀的状态和状态信息,用来填充秒杀结果类