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

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. springboot中使用druid和监控配置

    如果想要监控自己的项目的访问情况及查看配置信息,druid是一个很好的选择,可能你会问druid是什么?有什么用?优点是什么? Druid简介 Druid是阿里巴巴开源的数据库连接池,号称是Java语 ...

  2. JavaScript停止冒泡例子

    <!DOCTYPE html><html><head><meta charset="utf-8"><title>qypt ...

  3. c# axPageLayoutControl 加数据框

    private void axPageLayoutControl1_OnMouseDown(object sender, ESRI.ArcGIS.Controls.IPageLayoutControl ...

  4. 活字格企业 Web 应用生成器新手上路指南

    活字格是一款企业 Web 应用生成器,使用了类 Excel 的设计界面,通过简单的拖拽操作,就能快速制作出一个 Web 信息管理系统.在整个使用过程中无需专业软件知识,没有任何技术门槛,能轻松实现各行 ...

  5. Android ListView无数据项时提示

    只需要调用在代码中调用setEmptyView(View emptyView)设置ListView为空时显示这个TextView即可. 布局文件 <?xml version="1.0& ...

  6. mysql 客户端

    MySQL是基于C/S模式的数据库管理系统.MySQL公司开发了众多的客户端软件来帮助用户管理MySQL软件,最著名的就是 MySQL Command Line Client 和 MySQL-Work ...

  7. Android UI组件----自定义ListView实现动态刷新

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/3 ...

  8. 2.Java英文缩写详解

    1.JVM 2.JDK JRE 3.Java SE EE ME 4.OO OOP 5.IOC 6.SQL 7.POJO 1.JVM:Java Virtual Machine(Java虚拟机)的缩写. ...

  9. twemproxy源码分析

    twemproxy是twitter开源的redis/memcached 代理,数据分片提供取模,一致性哈希等手段,维护和后端server的长连接,自动踢除server,恢复server,提供专门的状态 ...

  10. 使用 PowerShell 创建 Linux 虚拟机

    Azure PowerShell 模块用于从 PowerShell 命令行或脚本创建和管理 Azure 资源. 本指南详细介绍了如何使用 Azure PowerShell 模块部署运行 Ubuntu ...