看到公司有个部门提出了这个问题,补个粗略的解决方案。。。

1.编写拦截器

/**
* Description: 防止重复提交
*
* @Author liam
* @Create Date: 2018/3/9 9:22
*/
public class AvoidReSubmitIntercepter extends HandlerInterceptorAdapter { private static final String SPLIT_FLAG = "_";
private static final String AVOID_RE_SUBMIT_TOKEN_KEY = "identifier_token"; @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (checkAvoidReSubmitTokenOn(handler,AvoidReSubmitBehavior.Check)) {
//验证是否重复
if (checkIsRepeatSubmit(request)) {
//重复提交
return false;
}
}
return super.preHandle(request, response, handler);
} @Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
if (checkAvoidReSubmitTokenOn(handler,AvoidReSubmitBehavior.Create)) {
Random random = new Random();
String uuid = UUID.randomUUID().toString().replace(SPLIT_FLAG, String.valueOf(random.nextInt()));
String tokenValue = String.valueOf(System.currentTimeMillis());
String transferToken = uuid + SPLIT_FLAG + tokenValue;
request.setAttribute(AVOID_RE_SUBMIT_TOKEN_KEY, transferToken);
request.getSession(true).setAttribute(uuid, tokenValue);
}
super.postHandle(request, response, handler, modelAndView);
} /**
* Description: 是否开启防重规则
*
* @Author liam
* @Create Date: 2018/3/9 10:33
*/
private boolean checkAvoidReSubmitTokenOn(Object handler,AvoidReSubmitBehavior behavior) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method invokeMethod = handlerMethod.getMethod();
AvoidReSubmitToken avoidReSubmitToken = invokeMethod.getAnnotation(AvoidReSubmitToken.class);
if (avoidReSubmitToken != null && avoidReSubmitToken.behavior().equals(behavior)) {
return true;
}
return false; } private boolean checkIsRepeatSubmit(HttpServletRequest request) {
String clientToken = request.getParameter(AVOID_RE_SUBMIT_TOKEN_KEY);
if (StringUtils.isEmpty(clientToken)) {
clientToken = request.getParameter(AVOID_RE_SUBMIT_TOKEN_KEY);
if (StringUtils.isEmpty(clientToken)) {
return true;
}
}
String[] clientTokensDetail = StringUtils.split(clientToken, SPLIT_FLAG);
if (clientTokensDetail.length == ) {
String uuid = clientTokensDetail[];
String token = clientTokensDetail[];
       //此处存在并发风险...阔以加锁处理
String serverToken = (String) request.getSession(true).getAttribute(uuid);
if (StringUtils.isNotEmpty(serverToken) && token.equals(serverToken)) {
request.getSession(true).removeAttribute(uuid);
return false;
}
}
return true;
}
}

提供开启规则的注解:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AvoidReSubmitToken { AvoidReSubmitBehavior behavior(); }

定义两种行为:

public enum  AvoidReSubmitBehavior {
Create,
Check;
}

拦截器的配置:

<!-- 拦截器配置 -->
<mvc:interceptors>
<!-- 配置Token拦截器,防止用户重复提交数据 -->
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="liam.AvoidReSubmitIntercepter"/>
</mvc:interceptor>
</mvc:interceptors>

Java代码使用;

    @AvoidReSubmitToken(behavior = AvoidReSubmitBehavior.Create)
@RequestMapping("test")
public String testPage() {
return "form/page";
}
@AvoidReSubmitToken(behavior = AvoidReSubmitBehavior.Check)
@RequestMapping("potHandler")
public String postHandler(){
return "ok";
}

页面代码:

<form id="" class="form-horizontal" action="${ctx}/postHandler" method="post">
......
<input type="hidden" name="token" value="${identifier_token}"/>
<!-- 注:name必须是identifier_token -->
......
</form>

其实该方案也可以验证提交数据是否有效,当然通常是把token放到只读的缓存了。。

伪代码。。没测试呢。。。

spring MVC 后台token防重复提交解决方案的更多相关文章

  1. SpringMVC后台token防重复提交解决方案

    本文介绍如何使用token来防止前端重复提交的问题. 目录 1.思路 2.拦截器源码实现 3.注解源码 4.拦截器的配置 5.使用指南 6.结语 思路 1.添加拦截器,拦截需要防重复提交的请求 2.通 ...

  2. Spring MVC表单防重复提交

    利用Spring MVC的过滤器及token传递验证来实现表单防重复提交. 创建注解 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RU ...

  3. spring mvc防止表单重复提交的代码片段

    1.定义一个token接口 package com.bigbigrain.token; import java.lang.annotation.Documented; import java.lang ...

  4. (亿级流量)分布式防重复提交token设计

    大型互联网项目中,很多流量都达到亿级.同一时间很多的人在使用,而每个用户提交表单的时候都可能会出现重复点击的情况,此时如果不做好控制,那么系统将会产生很多的数据重复的问题.怎样去设计一个高可用的防重复 ...

  5. 架构设计 | 接口幂等性原则,防重复提交Token管理

    本文源码:GitHub·点这里 || GitEE·点这里 一.幂等性概念 1.幂等简介 编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同.就是说,一次和多次请求某一个资源会产 ...

  6. 使用aop注解实现表单防重复提交功能

    原文:https://www.cnblogs.com/manliu/articles/5983888.html 1.这里采用的方法是:使用get请求进入表单页面时,后台会生成一个tokrn_flag分 ...

  7. (九)Struts2 防重复提交

    所有的学习我们必须先搭建好Struts2的环境(1.导入对应的jar包,2.web.xml,3.struts.xml) 第一节:重复提交示例演示 struts.xml <?xml version ...

  8. AJAX防重复提交的办法总结

    最近的维护公司的一个代理商平台的时候,客服人员一直反映说的统计信息的时候有重复数据,平台一直都很正常,这个功能是最近新进的一个实习生同事写的功能,然后就排查问题人所在,发现新的这个模块的AJAX提交数 ...

  9. struts2学习(15)struts2防重复提交

    一.重复提交的例子: 模拟一种情况,存在延时啊,系统比较繁忙啊啥的. 模拟延迟5s钟,用户点了一次提交,又点了一次提交,例子中模拟这种情况: 这样会造成重复提交:   com.cy.action.St ...

随机推荐

  1. react解决roadhog buildDll 【转】

    本地删了 node module 目录,重新安装的时候,提示 找了找,可如下解决 ------- 转自: https://www.cnblogs.com/huhanhaha/p/7605722.htm ...

  2. JS实现填报时对修改过的单元格进行标识

    1. 描述 在填报预览时,对单元格编辑后,其左上角有个红色标记,但非常不明显,用户很难注意到.有没有什么好的办法,对单元格操作后,将其做较明显的特殊标记处理,方便用户识别呢? 如图所示:对单元格进行操 ...

  3. android 每个块半径不同的扇形图,自定义view

    1.首先看效果图 2.自定义PieChartView,继承自View,下边为PieChartView代码 package com.yingjinbao.im.peach.customview; imp ...

  4. android 自定义控件之ViewGroup生命周期执行步骤

    前言 了解ViewGroup的生命周期的执行步骤对于自己自定义ViewGroup的时候十分重要,清楚了整个流程才能对ViewGroup有更深的理解.本文从个人的总结,来阐述一下执行的顺序.执行说明 首 ...

  5. linux 源码包之脚本安装包的安装

    脚本安装包 脚本安装包并不是独立的软件包类型,常见的实际是源码包.是人为地把安装过程写成了自动安装脚本,只要执行脚本,定义简单的参数,就可以完成安装.非常类似于windows软件的安装方式.在linu ...

  6. 前端构建工具 Gulp.js 上手实例

    在软件开发中使用自动化构建工具的好处是显而易见的.通过工具自动化运行大量单调乏味.重复性的任务,比如图像压缩.文件合并.代码压缩.单元测试等等,可以为开发者节约大量的时间,使我们能够专注于真正重要的. ...

  7. 团队项目个人进展——Day04

    一.昨天工作总结 冲刺第四天,昨天继续忙着整理数据结构与算法的知识,在项目上看了看有关视频,学习了有关视图的地方和文档说明 二.遇到的问题 无 三.今日工作规划 学习并实现地图的放大与缩小

  8. Oracle EBS 获取公司段的本位币

    SELECT gls.currency_code FROM hr_organization_information_v t, gl_sets_of_books gls WHERE t.org_info ...

  9. Oracle常见等待事件

    1Buffer busy waits从本质上讲,这个等待事件的产生仅说明了一个会话在等待一个Buffer(数据块),但是导致这个现象的原因却有很多种.常见的两种是: ·         当一个会话视图 ...

  10. asp.net MVC4 框架揭秘 读书笔记系列2

    1.2 MVC 变体 MVC 是一种Pattern 另外一种说法是ParaDigm 范例 模式和范例的区别在于前者可以应用到具体的应用上,而后者则仅仅提供一些指导方针 1.2.1 MVP Model ...