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

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. CentOS 7 防火墙端口配置

    CentOS 7 防火墙端口配置查看防火墙是否开启systemctl status firewalld 若没有开启则开启systemctl start firewalld 查看所有开启的端口firew ...

  2. CSDN博客大事日记1

    一.       2016-10-18,申请了博客专家,但是因为PV不够,所以很荣幸的成为了一名CSDN准博客专家,接下,得更加努力了争取早日成为博客专家,在此立帖为证哦.               ...

  3. 根据自定义区域裁剪ArcGIS切片地图服务

    切片地图服务是访问地图最快捷的服务方式.假如要根据地理区域对切图进行访问控制,往往只能针对不同地理区域制作相应的地图,并发布为切片地图服务.而一般在切图的时候又是按全区域实施的,所以给切片管理者造成不 ...

  4. Flutter Stack布局中定位的方式

    前言 想要记录一下Stack布局中,定位的两种方式 代码 //……省略无关代码…… child: new Column( children: <Widget>[ new SizedBox( ...

  5. 深入浅出React的一些细节——State

    (来源于: https://facebook.github.io/react/docs/state-and-lifecycle.html 翻译by:@TimRChen) Using State Cor ...

  6. MySQL上机实习报告(一)

    一.实习内容    利用wamp进行MySQL上机实习,建立数据库和一个学生信息表,并能对建的表进行数据插入.修改.查询和删除等内容. 二.实习目的 能将课堂上所学的内容运用到实际的上机操作中,进一步 ...

  7. 标准的Flask启动文件

    最近有一些同学问了我一些项目结构的问题 所以今天给大家专门讲解 解耦后的项目 目录我会分为两种方式:一种是普通解耦 一种是多mvc解耦 首先 我没先建立我们程序的文件夹并且在这个文件夹内写一个和这个文 ...

  8. http协议的状态码——400,401,403,404,500,502,503,301,302等常见网页错误代码

    http协议的状态码 1xx(临时响应) 表示临时响应并需要请求者继续执行操作的状态码. 100(继续) 请求者应当继续提出请求.服务器返回此代码表示已收到请求的第一部分,正在等待其余部分. 101( ...

  9. Spring 如何在 WEB 应用中使用

    1. Spring 如何在 WEB 应用中使用 ? 1). 需要额外加入的 jar 包: spring-web-4.0.0.RELEASE.jar spring-webmvc-4.0.0.RELEAS ...

  10. 【转】爬虫的一般方法、异步、并发与框架scrapy的效率比较

    该文非原创文字,文字转载至  jclian91  链接:https://www.cnblogs.com/jclian91/p/9799697.html Python爬虫的N种姿势   问题的由来    ...