参考链接:
防表单重复提交的四种方法:https://www.cnblogs.com/huanghuizhou/p/9153837.html
补充几点个人想法:
1. 对于前后端传递token验证的方式,每次都需要页面加载才能在后端存放token,这样会导致用户在第一次提交表单失败后就无法提交成功,需要刷新页面。
2. 利用session去给前后端的token存放获取,这对于APP来说不协调,适合用redis。

使用哪种方法要根据自己项目去考虑,比如单纯做网页的用session也不错。
我这里后台是提供给微信端和APP端,所以使用了第四种方法:使用Redis和AOP自定义切入实现
好处是校验只在后端完成,不需要前端传递token之类的,这里直接从链接中拿出来(进行少许改动,防丢,哈哈)
注意:这个方法需要自己指定防重复提交的间隔时间,在这个时间内都不能提交第二次,过了这个时间就能提交,所以时间需要把控好,可以算优点也能是缺点
实现原理:

  1. 自定义防止重复提交标记(@AvoidRepeatableCommit)。
  2. 对需要防止重复提交的Congtroller里的mapping方法加上该注解。
  3. 新增Aspect切入点,为@AvoidRepeatableCommit加入切入点。
  4. 每次提交表单时,Aspect都会保存当前key到reids(须设置过期时间)。
  5. 重复提交时Aspect会判断当前redis是否有该key,若有则拦截。

自定义标签

 import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;/*** 避免重复提交* @author hhz* @version* @since*/@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface AvoidRepeatableCommit {/*** 指定时间内不可重复提交,单位秒* @return*/long timeout()  default 5 ;}

自定义切入点Aspect

package com.xx.web;import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;import javax.servlet.http.HttpServletRequest;import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;import com.alibaba.fastjson.JSON;
import com.xx.web.util.DynamicRedisUtil;
import com.xx.web.util.IPUtil;/*** 重复提交aop* * @author * @date */
@Aspect
@Component
@EnableAspectJAutoProxy(exposeProxy=true)
public class AvoidRepeatableCommitAspect {@Autowired HttpServletRequest request; //这里可以获取到request/*** @param point*/@Around("@annotation(com.xx.web.AvoidRepeatableCommit)")public Object around(ProceedingJoinPoint point) throws Throwable {String ip = IPUtil.getIpAddr(request);//获取注解MethodSignature signature = (MethodSignature) point.getSignature();Method method = signature.getMethod();//目标类、方法String className = method.getDeclaringClass().getName();String name = method.getName();String ipKey = String.format("%s#%s",className,name);int hashCode = Math.abs(ipKey.hashCode());String key = String.format("%s_%d",ip,hashCode);
//        log.info("ipKey={},hashCode={},key={}",ipKey,hashCode,key);AvoidRepeatableCommit avoidRepeatableCommit =  method.getAnnotation(AvoidRepeatableCommit.class);int timeout = avoidRepeatableCommit.timeout();if (timeout < 0){timeout = 5;}//用多参数set方法保证对redis操作原子性Integer isSuccess = DynamicRedisUtil.setnxAndExpire(key, UUID.randomUUID().toString(), timeout*1000, DynamicRedisUtil.AVOID_REPEATABLE_COMMIT_DB);if (isSuccess == 0) {resultMap.put("errCode", 10001);resultMap.put("errMsg", "请勿重复提交");return JSON.toJSONString(resultMap);}//执行方法Object object = point.proceed();return object;}}/*** redis工具类方法* 比setnx多了个保存失效时间* @author wangdy* @date 2018年8月13日 下午2:38:07* @param key* @param value* @param seconds 失效时间,单位秒* @param db* @return 当key不存在,保存成功并返回1,当key已存在不保存并返回0*/public static Integer setnxAndExpire(final String key, String value, long milliseconds, int db) {JedisPool pool = getPool();Jedis jds = null;boolean broken = false;int setnx = 0;try {jds = pool.getResource();jds.select(db);String result = jds.set(key, value, "NX", "PX", milliseconds);if ("OK".equals(result)) {setnx = 1;}return setnx;} catch (Exception e) {broken = true;logger.error("setString:" + e.getMessage());} finally {if (broken) {pool.returnBrokenResource(jds);} else if (jds != null) {pool.returnResource(jds);}}return setnx;}

Rest方法:

//重复提交测试@RequestMapping(value = "testCommit",method = {RequestMethod.GET,RequestMethod.POST})@ResponseBody@AvoidRepeatableCommit(timeout = 3)public String testCommit(HttpServletRequest request){Map<String,Object> resultMap = new HashMap<String,Object>();try{    resultMap.put("success", true);}catch (Exception e) {e.printStackTrace();resultMap.put("success", false);}return JSON.toJSONString(resultMap);}

redis防表单重复提交相关推荐

  1. JavaWeb -- Struts1 使用示例: 表单校验 防表单重复提交 表单数据封装到实体

    1. struts 工作流程图 超链接 2. 入门案例 struts入门案例:1.写一个注册页面,把请求交给 struts处理<form action="${pageContext.r ...

  2. SpringMVC中实现的token,防表单重复提交

    一:首先创建一个token处理类  ,这里的类名叫 TokenHandler private static Logger logger = Logger.getLogger(TokenHandler. ...

  3. Spring Boot中防表单重复提交以及拦截器登录检测

    目录 理论 演示 源码 理论 在用户登录后,如果按F5刷新会出现表单重复提交的问题,解决这个问题后,如果没有拦截器登录检测,就会造成,任意用户可以登录后台界面,所以要有拦截器登录检测. 相关的逻辑步骤 ...

  4. 基于拦截器实现防表单重复提交

    1.定义自定义注解 2.定义防重复提交拦截器 /*** 防止重复提交拦截器** */ @Component public abstract class RepeatSubmitInterceptor ...

  5. redis防止表单重复提交

    1. 对于前后端传递token验证的方式,每次都需要页面加载才能在后端存放token,这样会导致用户在第一次提交表单失败后就无法提交成功,需要刷新页面.  2. 利用session去给前后端的toke ...

  6. 简单介绍redis分布式锁解决表单重复提交的问题

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

  7. 表单重复提交(前端未做单击防重复点击策略)

    表单重复提交导致重复添加,用token解决:提交前的请求会给前端一token,后端将这token存在缓存中,表单提交时要带上这token,后端校验token通过执行业务逻辑,后端 并删除缓存中的tok ...

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

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

  9. java后端 防重复提交_后台防止表单重复提交

    具体的做法: 1.获取用户填写用户名和密码的页面时向后台发送一次请求,这时后台会生成唯一的随机标识号,专业术语称为Token(令牌). 2.将Token发送到客户端的Form表单中,在Form表单中使 ...

最新文章

  1. redis 中 set 和 hset 有什么不同,什么时候使用 hset 什么时候使用set?
  2. Mac OS 上安装 PostgreSQL
  3. [sh]top添加到crontab不生效问题解决
  4. Lesson 14.3 Batch Normalization综合调参实战
  5. Vue报错Module not found: Error: Can‘t resolve ‘less-loader‘
  6. 电机控制pid_微电机控制如此简单,揭秘微电机调速的控制,PID控制之双环调速...
  7. server精简版代理意外终止 sql_来自阿里巴巴内部JAVA面试宝典意外流出
  8. 设计模式(17) 访问者模式(VISITOR) C++实现
  9. 厚积薄发!华为云7篇论文被AAAI收录,2021年AI行业技术风向标看这里!
  10. 计算机系统层次中 从上层,在计算机系统层次结构中下层是上层的上层是下层的一个.ppt...
  11. 小程序切换账户拉取仓库文件的appid提示
  12. keyshot分辨率多少合适_分辨率单位及换算详解
  13. 固态硬盘用软件测试掉速严重,固态硬盘为什么会“掉速”?
  14. 学习路线、站点推荐、工具软件、资源下载
  15. 336亿的生意——你所不了解的Dapp这一年(下)
  16. PADS输出BOM表和位号图(装配图)
  17. 湖北民院OJ 计算球体体积
  18. 2019第五届中国诗歌春晚致敬先贤
  19. Axon Framework官方文档(五)
  20. 奔腾cpu可以安装黑苹果吗_【2020】macOS黑苹果硬件主板CPU和显卡的支持列表和选购指南...

热门文章

  1. php的filetype,PHP filetype( )用法及代码示例
  2. ios调用百度地图智能联想搜索
  3. actionbar 兼容包几个注意点
  4. javascript写字技巧_js canvas实现写字动画效果
  5. 论写代码时逻辑要严谨的重要性
  6. linux内核态和用户态
  7. ORCAD LIBRARY BUILDER17.2使用
  8. allfinanz.cn全金域名价值超过一切金融域名
  9. windows 安装配置 pycharm 创建项目并运行代码
  10. 如何使用usbmon进行usb抓包调试