SpringBoot学习之高并发接口优化—–秒杀接口地址隐藏(验证码)+接口限流防刷
秒杀接口地址隐藏
思路:秒杀开始之前,先去请求接口获取秒杀地址。
- 接口改造,带上PathVariable参数
- 添加生成地址的接口
- 秒杀收到请求,先验证PathVariable
随机生成一个字符串,作为地址加在url上,然后生成的时候,存入 redis缓存中,根据前端请求的url获取path。 判断与缓存中的字符串是否一致,一致就认为对的。就可以执行秒杀操作,否则失败。
对于秒杀接口,不是直接去请求秒杀的这个接口了, 而是先请求下获取path。之后拼接成秒杀地址。
前端代码:
function getMiaoshaPath() {
goodsId:$("#goodsId").val(),
g_showLoading();
$.ajax({
url:"/miaosha/path",
type:"GET",
data:{
goodsId:$("#goodsId").val(),
verifyCode:$("#verifyCode").val()
},
success:function (data) {
if(data.code == 0){
var path = data.data;
doMiaosha(path);
}else {
layer.msg(data.msg);
}
},
error:function() {
layer.msg("客户端请求错误");
}
});
}
对应的后端代码:
@AccessLimit(seconds = 5,maxCount = 5, needLogin = true)
@RequestMapping(value = "/path",method = RequestMethod.GET)
@ResponseBody
public Result<String> getSecKillPath(HttpServletRequest request, SecKillUser user,
@RequestParam("goodsId") long goodsId,
@RequestParam(value = "verifyCode", defaultValue = "0") int verifyCode){
if (user == null){
return Result.error(CodeMsg.SESSION_ERROR);
}
//验证码的校验
boolean check = secKillService.checkVerifyCode(user,goodsId,verifyCode);
if (!check){
return Result.error(CodeMsg.REQUEST_ILLEGAL);
}
//生成path
String path = secKillService.createSecKillPath(user,goodsId);
return Result.success(path);
}
生成path,存入redis中
public String createSecKillPath(SecKillUser user, Long goodsId) {
if (user == null || goodsId <= 0){
return null;
}
String str = MD5Util.md5(UUIDUtil.uuid() + "123456");
redisService.set(SecKillKey.getPath,user.getId()+"_"+goodsId,str);
return str;
}
秒杀接口,先拿到这个path验证一下是否正确,正确再进入下面的逻辑:
//验证path
boolean check = secKillService.checkPath(user,goodsId,path);
if (!check){
return Result.error(CodeMsg.REQUEST_ILLEGAL);
}
具体的验证,就是取出缓存中的path,与前端传来的path进行对比,相等,说明是这个用户发来的请求:
/**
* 验证秒杀接口参数
* @param user
* @param goodsId
* @param path
* @return
*/
public boolean checkPath(SecKillUser user, long goodsId, String path) {
if (user == null || path == null){
return false;
}
String pathOld = redisService.get(SecKillKey.getPath,""+user.getId()+"_"+goodsId,String.class);
return path.equals(pathOld);
}
然后前端拼接出秒杀的地址
function doMiaosha