JAVA高并发秒杀系统构建之——Service层

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是一个枚举类,主要是封装秒杀的状态和状态信息,用来填充秒杀结果类
这里写图片描述
这里写图片描述


目前为止,Service层的业务逻辑已经全部搞定,下篇将进行Web层的讲解

java实现秒杀系统@Controller @RequestMapping("seckill")//url:/模块/资源/{id}/细分 /seckill/list public class SeckillController { private final Logger logger = LoggerFactory.getLogger(this.getClass()); @Autowired private SeckillService seckillService; @RequestMapping(value="/list",method = RequestMethod.GET) public String list(Model model){ //获取列表页 List list=seckillService.getSeckillList(); model.addAttribute("list",list); //list.jsp+model = ModelAndView return "list";//WEB-INF/jsp/"list".jsp } @RequestMapping(value = "/{seckillId}/detail",method = RequestMethod.GET) public String detail(@PathVariable("seckillId") Long seckillId, Model model){ if (seckillId == null){ return "redirect:/seckill/list"; } Seckill seckill = seckillService.getById(seckillId); if (seckill == null){ return "forward:/seckill/list"; } model.addAttribute("seckill",seckill); return "detail"; } //ajax json @RequestMapping(value = "/{seckillId}/exposer", method = RequestMethod.POST, produces = {"application/json;charset=UTF-8"}) @ResponseBody public SeckillResult exposer(@PathVariable("seckillId") Long seckillId){ SeckillResult result; try { Exposer exposer =seckillService.exportSeckillUrl(seckillId); result = new SeckillResult(true,exposer); } catch (Exception e) { logger.error(e.getMessage(),e); result = new SeckillResult(false,e.getMessage()); } return result; } @RequestMapping(value = "/{seckillId}/{md5}/execution", method = RequestMethod.POST, produces = {"application/json;charset=UTF-8"} ) @ResponseBody public SeckillResult execute(@PathVariable("seckillId")Long seckillId,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值