SpringBoot学习之高并发接口优化—–秒杀接口地址隐藏(验证码)+接口限流防刷
秒杀接口地址隐藏
思路:秒杀开始之前,先去请求接口获取秒杀地址。
1 | - 接口改造,带上PathVariable参数 |
随机生成一个字符串,作为地址加在url上,然后生成的时候,存入 redis缓存中,根据前端请求的url获取path。 判断与缓存中的字符串是否一致,一致就认为对的。就可以执行秒杀操作,否则失败。
对于秒杀接口,不是直接去请求秒杀的这个接口了, 而是先请求下获取path。之后拼接成秒杀地址。
前端代码:
1 | function getMiaoshaPath() { |
对应的后端代码:
1 | 5,maxCount = 5, needLogin = true) (seconds = |
生成path,存入redis中
1 | public String createSecKillPath(SecKillUser user, Long goodsId) { |
秒杀接口,先拿到这个path验证一下是否正确,正确再进入下面的逻辑:
1 | //验证path |
具体的验证,就是取出缓存中的path,与前端传来的path进行对比,相等,说明是这个用户发来的请求:
1 | /** |
然后前端拼接出秒杀的地址
1 | function doMiaosha(path){ |
公式验证码
思路:点击秒杀之前,先输入验证码,分散用户的请求
1 |
前端增加获取验证码显示验证码输入验证码上传。
1 | <div class="row"> |
增加返回验证码的接口
1 | /** |
在每次秒杀的时候,要先判断这个验证码是否正确
1 | //验证码的校验 |
生成数字验证码并存入redis中,判断也是从redis中取出来判断
1 | public BufferedImage createSecKillVerifyCode(SecKillUser user, long goodsId) { |
前端在function getMiaoshaPath()这个函数中将结果传到后端,后端在这个获取真正秒杀链接的时候进行判断是否正确:
1 | verifyCode:$("#verifyCode").val() |
后端接收验证码验证
1 | 5,maxCount = 5, needLogin = true) (seconds = |
redis中取出生成时存入的验证码并与前端传进来的验证码做校验
1 | /** |
接口限流防刷
思路:对接口做限流
可以使用拦截器减少对业务的侵入
点击秒杀之后,首先是生成path,那假如我们对这个接口进行限制:5秒之内用户只能点击5次。
这放在redis中是非常好实现的,因为redis有个自增(自减)和缓存时间,可以很好地实现这个效果。
这里使用注解的方式来实现接口的限流防刷,使用注解的话就可以做成通用的方法,在你想使用限流防刷的接口就可以添加上该注解
假设,我想在5秒内最多请求5次,并且必须要登陆:相应的注解就是这样的:
1 | @AccessLimit(seconds = 5,maxCount = 5,needLogin = true) |
首先是实现这个注解:
1 | package com.springboot.SecKill.access; |
要想这个注解能够生效,必须要配置拦截器AccessInterceptor:
1 | package com.springboot.SecKill.access; |
要想这个拦截器工作,我们要重写WebMvcConfigurerAdapter中的addInterceptors方法,将我们的拦截器添加进去就可以了:
1 | public void addInterceptors(InterceptorRegistry registry) { |
这样,利用注解和拦截器就实现了接口通用的限流功能。