在系统中,有些接口如果重复提交,可能会造成脏数据或者其他的严重的问题,所以我们一般会对与数据库有交互的接口进行重复处理。本文就详细的介绍一下redis分布式锁解决表单重复提交,感兴趣的可以了解一下

假如用户的网速慢,用户点击提交按钮,却因为网速慢,而没有跳转到新的页面,这时的用户会再次点击提交按钮,举个例子:用户点击订单页面,当点击提交按钮的时候,也许因为网速的原因,没有跳转到新的页面,这时的用户会再次点击提交按钮,如果没有经过处理的话,这时用户就会生成两份订单,类似于这种场景都叫重复提交。

使用redis的setnx和getset命令解决表单重复提交的问题。

1.引入redis依赖和aop依赖

    org.springframework.bootspring-boot-starter-redis1.3.8.RELEASEorg.springframework.bootspring-boot-starter-aop

2.编写加锁和解锁的方法。

/*** @author wangbin* @description redis分布式锁* @date 2019年09月20日*/
@Component
public class RedisLock {private final Logger logger = LoggerFactory.getLogger(RedisLock.class);@Autowiredprivate StringRedisTemplate redisTemplate;/*** @author wangbin* @description 进行加锁的操作(该方法是单线程运行的)* @date 2019年09月20日* @param key 某个方法请求url加上cookie中的用户身份使用md5加密生成* @param value 当前时间+过期时间(10秒)* @return true表示加锁成功   false表示未获取到锁*/public boolean lock(String key,String value){//加锁成功返回trueif(redisTemplate.opsForValue().setIfAbsent(key,value,10, TimeUnit.SECONDS)){return true;}String currentValue = redisTemplate.opsForValue().get(key);//加锁失败,再判断是否由于解锁失败造成了死锁的情况if(StringUtils.isNotEmpty(currentValue) && Long.parseLong(currentValue) < System.currentTimeMillis()){//获取上一个锁的时间,并且重新设置锁String oldValue = redisTemplate.opsForValue().getAndSet(key, value);if(StringUtils.isNotEmpty(oldValue) && oldValue.equals(currentValue)){//设置成功,重新设置锁是保证了单线程的运行return true;}}return false;}/*** @author wangbin* @description 进行解锁的操作* @date 2019年09月20日* @param key 某个方法请求url使用md5加密生成* @param value 当前时间+过期时间* @return*/public void unLock(String key,String value){try {String currentValue = redisTemplate.opsForValue().get(key);if(StringUtils.isNotEmpty(currentValue) && currentValue.equals(value)){redisTemplate.delete(key);}}catch (Exception e){logger.error("redis分布式锁,解锁异常",e);}}/*** @author wangbin* @description 进行解锁的操作* @date 2019年09月20日* @param key 某个方法请求url使用md5加密生成* @return*/public void unLock(String key){try {String currentValue = redisTemplate.opsForValue().get(key);if(StringUtils.isNotEmpty(currentValue)){redisTemplate.delete(key);}}catch (Exception e){logger.error("redis分布式锁,解锁异常",e);}}
}

3.使用拦截器在请求之前进行加锁的判断。

@Configuration
public class LoginInterceptor extends HandlerInterceptorAdapter {private final Logger logger = LoggerFactory.getLogger(LoginInterceptor.class);//超时时间设置为10秒private static final int timeOut = 10000;@Autowiredprivate StringRedisTemplate stringRedisTemplate;@Autowiredprivate RedisLock redisLock;/*** 在请求处理之前进行调用(Controller方法调用之前)* 基于URL实现的拦截器* @param request* @param response* @param handler* @return* @throws Exception*/@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {String path = request.getServletPath();if (path.matches(Constants.NO_INTERCEPTOR_PATH)) {//不需要的拦截直接过return true;} else {// 这写你拦截需要干的事儿,比如取缓存,SESSION,权限判断等//判断是否是重复提交的请求if(!redisLock.lock(DigestUtils.md5Hex(request.getRequestURI()+value),String.valueOf(System.currentTimeMillis()+timeOut))){logger.info("===========获取锁失败,该请求为重复提交请求");return false;}return true;}}
}

4.使用aop在后置通知中进行解锁。

/*** @author wangbin* @description 使用redis分布式锁解决表单重复提交的问题* @date 2019年09月20日*/
@Aspect
@Component
public class RepeatedSubmit {@Autowiredprivate RedisLock redisLock;//定义切点@Pointcut("execution(public * com.kunluntop.logistics.controller..*.*(..))")public void pointcut(){}//在方法执行完成后释放锁@After("pointcut()")public void after(){ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();redisLock.unLock(DigestUtils.md5Hex(request.getRequestURI()+ CookieUtils.getCookie(request,"userkey")));}
}

到此这篇关于redis分布式锁解决表单重复提交的问题的文章就介绍到这了。

简单介绍redis分布式锁解决表单重复提交的问题相关推荐

  1. php mysql 重复提交数据_如何真正解决表单重复提交问题php代码

    如何真正解决表单重复提交问题php代码 过去一切时代的精华尽在书中.以下是小编为大家搜索整理的如何真正解决表单重复提交问题php代码,希望能给大家带来帮助!更多精彩内容请及时关注我们应届毕业生考试网! ...

  2. springboot 订单重复提交_防止表单重复提交(springboot,redis)

    我们在web项目中经常需要在后台对用户提交的表单进行校验防止重复提交.下面通过springboot的aop.redis来解决表单重复提交的问题. 通过在controller加上CheckSubmitF ...

  3. 防止表单重复提交的简单有效的策略

    点击提交按钮两次. 点击刷新按钮. 使用浏览器后退按钮重复之前的操作,导致重复提交表单. 使用浏览器历史记录重复提交表单. 浏览器重复的HTTP请求.用户提交表单时可能因为网速的原因,或者网页被恶意刷 ...

  4. 关于防止表单重复提交

    Struts的Token(令牌)机制能够很好的解决表单重复提交的问题,基本原理是:服务器端在处理到达的请求之前,会将请求中包含的令牌值与保存在当前用户会话中的令牌值进行比较,看是否匹配.在处理完该请求 ...

  5. spring boot 学习(七)小工具篇:表单重复提交

    注解 + 拦截器:解决表单重复提交 前言 学习 Spring Boot 中,我想将我在项目中添加几个我在 SpringMVC 框架中常用的工具类(主要都是涉及到 Spring AOP 部分知识).比如 ...

  6. 12、Struts2表单重复提交

    什么是表单重复提交 表单的重复提交: 若刷新表单页面, 再提交表单不算重复提交. 在不刷新表单页面的前提下: 多次点击提交按钮 已经提交成功, 按 "回退" 之后, 再点击 &qu ...

  7. JavaWeb学习总结(十三)——使用Session防止表单重复提交

    在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 一.表单重复提 ...

  8. JAVA_OA(十四)番外:JAVAWEB防止表单重复提交的方法整合(包括集群部署)

    因为自己要用,所以查找了网络上javaweb项目防止表单重复提交的方法,有些部分不太好找,所以整合后贴出来,首先是孤傲苍狼的一部分博客文章,集群部署的解决方案在后面(注意大红字) 原文出处:孤傲苍狼的 ...

  9. java怎么防止表单重复提交_如何防止表单重复提交

    在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 一.表单重复提 ...

最新文章

  1. 全球及中国偶联单克隆抗体行业深度调研及项目风险评估报告2021-2027年
  2. 这是80%的程序员都看过的python教程,你掌握了么?
  3. 物联网os_用于物联网的FireFox OS,NextCloud公告以及更多新闻
  4. 为什么不邀请我参加会议?
  5. [JSON].getObj( keyPath )
  6. axios 简单常用笔记
  7. 【跃迁之路】【586天】程序员高效学习方法论探索系列(实验阶段343-2018.09.14)...
  8. 算法学习——递归和排列组合
  9. php抓取网络电视源,电视直播源抓取工具箱
  10. 今天分享一下做支付宝小程序遇到的坑。ISV权限不足,建议在开发者中心检查对应功能是否已经添加。验签出错,建议检查签名字符串或签名私钥与应用公钥是否匹配
  11. 135微信编辑html语言,135微信编辑器怎么在拉入的模板框框里添加文字
  12. 西部数据硬盘官网查询
  13. CentOS7和Ubuntu18.10下运行Qt Creator出现cannot find -lGL的问题的解决方案
  14. 计算机屏幕闪烁黑屏,台式机电脑。显示屏指示灯一直闪烁,屏幕黑屏。。...-显示器电源灯闪黑屏...
  15. linux下硬件检测工具,Linux硬件检测工具
  16. 高性能 JavaScriptの五 -- 快响应用户界面
  17. 前端开发中,js时间与时间戳的转换
  18. 淘宝产品上下架时间对宝贝排名权重影响
  19. 我的世界末日之后无限法则服务器,Last Day Rules官方版
  20. c语言adc0809小数点,ADC0809做AD转换的C程序

热门文章

  1. 跳跃游戏(判断是否可以跳到最后一个下标)
  2. 基于视觉的数学公式识别算法介绍
  3. 一个小改动,CNN输入固定尺寸图像改为任意尺寸图像
  4. 解析激光雷达中时序融合的研究现状和发展方向
  5. 基于OpenCV的直方图匹配
  6. 用于数字成像的双三次插值技术​
  7. 链表问题17—— 一种怪异的节点删除方式
  8. Flutter控件--Switch 和 SwitchListTile
  9. IBM首家发布了公有云中的裸机Kubernetes
  10. 使用python调用zabbix接口截取监控图并生成Word文档