使用aop注解实现表单防重复提交功能
原文:https://www.cnblogs.com/manliu/articles/5983888.html
1.这里采用的方法是:使用get请求进入表单页面时,后台会生成一个tokrn_flag分别放到session和request中,表单页面用一个隐藏域储存该token_flag,在提交表单时,将该token_flag一并提交到后台,后台将该token_flag和session中对比,只要比对通过就立即删除session中的token_flag,这样就能保证表单最多只有一次成功提交的机会。
2.表单防重复提交一般前后端都会做,前端比较简单,点击过一次就将提交按钮置灰或disabled。
3.因为生成和验证token_flag具有通用性,一般不建议嵌入到具体方法中,最好的方法就是使用aop+注解的方式
4.注解

/**
* 表单注解,放在需要验证表单的方法上,一般是controller上
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface FormToken { }

5.AOP

@Aspect
@Component
public class ResubmitAspect {
private static final String PARAM_TOKEN = "token";
private static final String PARAM_TOKEN_FLAG = "TokenFlag_"; /**
* 执行切面拦截逻辑
*/
@Around("@annotation(formToken)")
public void execute(ProceedingJoinPoint joinPoint, FormToken formToken) throws Throwable {
if (formToken != null) {
//方法入参列表
Object[] args = joinPoint.getArgs();
//类名
String className = joinPoint.getTarget().getClass().getName();
for (Object arg : args) {
//方法入参是否包含request
if (arg != null && arg instanceof HttpServletRequest) {
HttpServletRequest request = (HttpServletRequest) arg;
HttpSession session = request.getSession(true);
if ("GET".equalsIgnoreCase(request.getMethod())) {
/* GET 生成 token */
this.generate(joinPoint, request, session, PARAM_TOKEN_FLAG + className);
} else {
/* POST 验证 token */
this.validation(joinPoint, request, session, PARAM_TOKEN_FLAG + className);
}
}
}
}
}
/**
* <p>
* 生成表单 token
* </p>
*/
public void generate(ProceedingJoinPoint joinPoint, HttpServletRequest request, HttpSession session,
String tokenFlag) throws Throwable {
String uuid = UUID.randomUUID().toString();
session.setAttribute(tokenFlag, uuid);
request.setAttribute(PARAM_TOKEN, uuid);
joinPoint.proceed();
}
/**
* <p>
* 验证表单 token
* </p>
* <p>
* 验证结果一致,既为第一次提交,删除会话中存储的token,并继续执行方法。<br>
* 否则不做任何处理。
* </p>
*/
public void validation(ProceedingJoinPoint joinPoint, HttpServletRequest request, HttpSession session,
String tokenFlag) throws Throwable {
Object sessionFlag = session.getAttribute(tokenFlag);
Object requestFlag = request.getParameter(PARAM_TOKEN);
if (sessionFlag != null && sessionFlag.equals(requestFlag)) {
//删除已验证的token
session.removeAttribute(tokenFlag);
joinPoint.proceed();
}
}
}

6.配置
在spring配置文件中
<aop:aspectj-autoproxy />
<context:component-scan base-package="com.baomidou.framework.aop">
</context:component-scan>
7.html中使用
<input type="hidden" name="token" value="${token}" />
使用aop注解实现表单防重复提交功能的更多相关文章
- Spring MVC表单防重复提交
利用Spring MVC的过滤器及token传递验证来实现表单防重复提交. 创建注解 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RU ...
- Token注解防止表单的重复提交
注解的一些基础: 参见http://blog.csdn.net/duo2005duo/article/details/50505884和 http://blog.csdn.net/duo2005duo ...
- struts2 文件的上传下载 表单的重复提交 自定义拦截器
文件上传中表单的准备 要想使用 HTML 表单上传一个或多个文件 须把 HTML 表单的 enctype 属性设置为 multipart/form-data 须把 HTML 表单的method 属性设 ...
- php中如何防止表单的重复提交
在php中如何防止表单的重复提交?其实也有几种解决方法. 下面小编就为大家介绍一下吧.需要的朋友可以过来参考下 代码: <?php /* * php中如何防止表单的重复提交 * by www.j ...
- php-- 避免表单的重复提交
用户提交表单时可能因为网速的原因,或者网页被恶意刷新,致使同一条记录重复插入到数据库中,这是一个比较棘手的问题.我们可以从客户端和服务器端一起着手,设法避免同一表单的重复提交. 1.使用客户端脚本 提 ...
- Session机制三(表单的重复提交)
1.表单的重复提交的情况 在表单提交到一个servlet,而servlet又通过请求转发的方式响应了一个JSP页面,这个时候地址栏还保留这servlet的那个路径,在响应页面点击刷新. 在响应页面没有 ...
- HttpSession解决表单的重复提交
1). 重复提交的情况: ①. 在表单提交到一个 Servlet, 而 Servlet 又通过请求转发的方式响应一个 JSP(HTML) 页面, 此时地址栏还保留着 Serlvet 的那个路径, 在响 ...
- Struts2 - 表单的重复提交问题
用户重复提交表单在某些场合将会造成非常严重的后果.例如,在使用信用卡进行在线支付的时候,如果服务器的响应速度太慢,用户有可能会多次点击提交按钮,而这可能导致那张信用卡上的金额被消费了多次.因此,重复提 ...
- HttpSession之表单的重复提交 & 验证码
如果采用 HttpServletResponse.sendRedirct() 方法将客户端重定向到成功页面,将不会出现重复提交问题 1.表单的重复提交 1). 重复提交的情况: ①. 在表单提交到一个 ...
随机推荐
- 正则表达式\s空格,\d数字,量词+*?测试
之前的博文中: 有正则表达式的\b.i.\g,本文再测试了空格数字和量词的匹配.这篇只测试匹配,不替换或其他处理.\s空格:测试实际写空格也能识别,但是不利于看出空了几个空格,可以用\s代表空格.\d ...
- jquery img src赋值
不用Jquery时:document.getElementById("imageId").src = "xxxx.jpg"; 用Jquery时:$(" ...
- APP排查内存泄漏最简单和直观的方法
内存泄漏无疑会严重影响用户体验,一些本应该废弃的资源和对象无法被释放,导致手机内存的浪费,app使用的卡顿,那么如何排查内存泄漏呢? 当然,首先我们有google的官方文档可以参考,大部分博客 ...
- 【GStreamer开发】GStreamer播放教程07——自定义playbin2的sink
目标 通过手动选择音频和视频的sink,playbin2可以进一步定制.这允许使用playbin2的应用在解码后可以自行做最终的渲染和显示.本教程展示了: 如何替换playbin2选择的sink 如何 ...
- PHP实现单点登录最简单的方法
PHP实现单点登录最简单的方法 用户在A登录 存入登录状态 登录B站(A的识别要传入B) 获取A的登录状态
- Spark 基础操作
1. Spark 基础 2. Spark Core 3. Spark SQL 4. Spark Streaming 5. Spark 内核机制 6. Spark 性能调优 1. Spark 基础 1. ...
- C++编译提示 default argument are given of parameter ..
如果定义一个类的构造函数时,带有默认的入参值,在cpp文件中实现构造函数时,是不能带的!否则就会提示该种类型的编译错误. //.h文件: namespace Ui { class Task; } cl ...
- [转帖]JAVA虚拟机和安卓虚拟机的区别
作者:天光链接:https://www.zhihu.com/question/20207106/answer/14654536来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出 ...
- Spring之28:AliasRegistry&SimpleAliasRegistry
AliasRegistry接口定义了alias的基本操作. package org.springframework.core; public interface AliasRegistry { //对 ...
- 修改主机名和修改主机映射和ssh免登陆
1.修改主机名 vim /etc/sysconfig/network NETWORKING=yes HOSTNAME=cc3 2.修改主机映射 vi /etc/hosts 127.0.0.1 loca ...