在平时的开发中我们都需要处理重复提交的问题,避免业务出错或者产生脏数据,虽然可以通过前端控制但这并不是可以完全避免,最好的方式还是前后端均进行控制,这样的话就可以更有效,尽可能全面的去减少错误的发生。
如果用户频繁点击或者恶意攻击的话就会造成不断的请求对服务器产生很大的压力,为了避免这种情况我们需要做处理。
怎样解决?工作中用过的方案有三种:
1.js层面,在用户点击提交订单后禁用按钮,然而这个是治标不治本的;
2.我们可以使用Redis incrde 原子性递增,来解决这种高并发的秒杀或者分布式序列号生成等场景。鉴于本场景我们只用他来做计数实现间隔时间内只接收一次请求。
实现逻辑:在提交订单之后使用Redis的incr设置一个递增的KEY(根据自己的需要设定但是要保证每一个人的唯一),来判断该KEY的数值,如果等于1说明这是第一次请求,发送短信记录日志,并设置有效期,如果不等于的话说明是间隔时间内多次请求,就提示请求频繁,稍后重试。
String orderNum=memberId+productId;
long count = redisTemplate.opsForValue().increment(orderNum, 1);
if (count == 1) {
//设置有效期2秒
redisTemplate.expire(orderNum, 2, TimeUnit.SECONDS);
}
if (count > 1) {
resultMap.put("retCode", "500");
resultMap.put("retMsg", "请不要重复提交订单");
return resultMap;
}
3.token机制解决
1.客户端申请token
2.服务器端生成token,并存放在session中,同时将token发送到客户端
3.客户端存储token,在请求提交时,同时发送token信息
4.服务器端统一拦截同一个用户的所有请求,验证当前请求是否需要被验证(不是所有请求都验证重复提交)
5.验证session中token是否和用户请求中的token一致,如果一致则放行
6.session清除会话中的token,为下一次的token生成作准备
7.并发重复请求到来,验证token和请求token不一致,请求被拒绝