文档章节

Spring MVC防止数据重复提交

Leons
 Leons
发布于 2015/07/08 11:17
字数 526
阅读 32
收藏 0

        要解决重复提交,有很多办法,比如说在提交完成后redirect一下,也可以用本文提到的使用token的方法(我不使用redirect是因为那样解决不了ajax提交数据或者移动应用提交数据,另一个原因是现在比较通行的方法是使用token,像python里的django框架也是使用token来解决)。

        使用token的逻辑是,给所有的url加一个拦截器,在拦截器里面用java的UUID生成一个随机的UUID并把这个UUID放到session里面,然后在浏览器做数据提交的时候将此UUID提交到服务器。服务器在接收到此UUID后,检查一下该UUID是否已经被提交,如果已经被提交,则不让逻辑继续执行下去…

      好的,来点实际代码,也许实际代码才是最好的老师:
注解Token代码:




@Target (ElementType.METHOD)

@Retention(RetentionPolicy.RUNTIME)

public @interface Token {

 

    boolean save() default false;

 

    boolean remove() default false;

}

拦截器TokenInterceptor代码:




public class TokenInterceptor extends HandlerInterceptorAdapter {

 

    @Override

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        if (handler instanceof HandlerMethod) {

            HandlerMethod handlerMethod = (HandlerMethod) handler;

            Method method = handlerMethod.getMethod();

            Token annotation = method.getAnnotation(Token.class);

            if (annotation != null) {

                boolean needSaveSession = annotation.save();

                if (needSaveSession) {

                    request.getSession(false).setAttribute("token", UUID.randomUUID().toString());

                }

                boolean needRemoveSession = annotation.remove();

                if (needRemoveSession) {

                    if (isRepeatSubmit(request)) {

                        return false;

                    }

                    request.getSession(false).removeAttribute("token");

                }

            }

            return true;

        } else {

            return super.preHandle(request, response, handler);

        }

    }

 

    private boolean isRepeatSubmit(HttpServletRequest request) {

        String serverToken = (String) request.getSession(false).getAttribute("token");

        if (serverToken == null) {

            return true;

        }

        String clinetToken = request.getParameter("token");

        if (clinetToken == null) {

            return true;

        }

        if (!serverToken.equals(clinetToken)) {

            return true;

        }

        return false;

    }

}

然后在Spring MVC的配置文件里加入:

XHTML


    <!-- 拦截器配置 -->

    <mvc:interceptors>

        <!-- 配置Token拦截器,防止用户重复提交数据 -->

        <mvc:interceptor>

            <mvc:mapping path="/**"/>

            <bean class="com.storezhang.web.spring.TokenInterceptor"/>

        </mvc:interceptor>

    </mvc:interceptors>

相关代码已经注释,相信你能看懂。
关于这个方法的用法是:在需要生成token的controller上增加@Token(save=true),而在需要检查重复提交的controller上添加@Token(remove=true)就可以了。
另外,你需要在view里在form里增加下面代码:

XHTML

1

<input type="hidden" name="token" value="${token}" />

已经完成了,去试试看你的数据还能重复提交了吧。


本文转载自:http://blog.icoolxue.com/submitted-by-spring-mvc-to-prevent-data-duplication/

Leons
粉丝 4
博文 42
码字总数 40935
作品 0
黄浦
架构师
私信 提问
表单防重复提交

防止表单重复提交 介绍了使用 redirect 技术防止表单提交,但是 redirect 解决不了后退到表单页面时重复提交表单,为了解决这个问题,加入了 token 的机制。如果每个 form 相关的处理方法中都...

NotFoundException
2015/09/06
191
0
spring 拦截器

数据源的 不起作用一样被拦截

湖底数星星
2017/08/24
66
0
Spring MVC拦截器+注解方式实现防止表单重复提交多线程问题

最近要把系统重复提交的问题解决: 参考了比较普遍的2种方案: 1、前端通过cookie(变量)状态来控制; 2、通过后台状态控制 现在想用第二种方案来解决问题,但是参照了下面文章来处理;快速...

Doug
2016/03/04
318
0
spring mvc 自带防止重复提交的功能?

我没有用Struts2 本想自己通过spring拦截器实现一个防止重复提交的功能 但是发现好像spring已经实现了 不知道是哪里的配置 我的spring版本是:3.2.5.RELEASE...

melnnyy
2014/07/24
382
0
基于注解的 Spring MVC 简单入门

以下内容是经过自己整理资料、官方文档所得: web.xml 配置: 这样,所有的.htm的请求,都会被DispatcherServlet处理; 初始化 DispatcherServlet 时,该框架在 web 应用程序WEB-INF 目录中寻...

超级奶爸老谭
2010/07/07
176.6K
37

没有更多内容

加载失败,请刷新页面

加载更多

OSChina 周二乱弹 —— 吾不好梦中插人

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @鱼豆腐233 :#今日歌曲分享# 分享My Chemical Romance的单曲《I Don't Love You》: 《I Don't Love You》- My Chemical Romance 手机党少年们...

小小编辑
今天
91
7
ss5 vpn 安装(linux版本)

1. 创建一个文件夹 /ss5 你也可以自定义,不过后续的地方需要注意自己的地址 2. 下载ss5文件(如果你的服务器没有安装wget请使用 yum -y install wget 命令安装 如果连yum都没安装自己查去)(下...

太黑_thj
今天
2
0
八、RabbitMQ的集群原理

集群架构 写在前面 RabbitMQ集群是按照低延迟环境设计的,千万不要跨越WAN或者互联网来搭建RabbitMQ集群。如果一定要在高延迟环境下使用RabbitMQ集群,可以参考使用Shovel和Federation工具。...

XuePeng77
今天
5
0
mac系统下,brew 安装mysql,用终端可以连接,navicat却连接不上?

问题: 1.报错? 2059 - Authentication plugin 'caching_sha2_password' cannot be loaded: dlopen(../Frameworks/caching_sha2_password.so, 2): image not found 2.自己通过设置,已经把密......

写bug的攻城狮
昨天
3
0
老生常谈,HashMap的死循环

问题 最近的几次面试中,我都问了是否了解HashMap在并发使用时可能发生死循环,导致cpu100%,结果让我很意外,都表示不知道有这样的问题,让我意外的是面试者的工作年限都不短。 由于HashMap...

群星纪元
昨天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部