`

spring mvc重复提交拦截器方法

阅读更多

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
/**
 * 禁止表单重复提交拦截器
 *
 * */
public class DenyDuplicateFormSubmitInterceptor extends HandlerInterceptorAdapter {
    private FormManager formManager;
    
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler) throws Exception {
        boolean flag = true;
        String token = request.getParameter(Form.FORM_UNIQ_ID_FIELD_NAME);
        if (token != null) {
            if (formManager.hasForm(request, token)) {
                formManager.destroyToken(request, token);
            } else {
                flag = false;
                throw new Exception("表单重复提交或过期,令牌[" + token + "]");
            }
        }
        return flag;
    }
    public void setFormManager(FormManager formManager) {
        this.formManager = formManager;
    }
}

在Spring MVC的HandlerMapping中配置该拦截器,随后在需要表单验证的Controller里做如下修改:

1、注入FormManager实例,主要是用newForm()生成一个新的Form对象

2、在返回的ModelAndView里加入该Form对象,假设名称是form

3、页面的表单中加入如下隐藏域

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

代码中我去掉了些东西,应该还是能正常工作的,反正原理就是这么回事,呵呵。

抱歉打扰一下,我想说的是:
第二.你不必加同步锁,Session每个线程各有一份
第三.Map的value目的只是为了提供date,好替除最久未使用的token,但你不必for循环每一项吧,token每次put到map是经过你的代码的对吗?那么你很轻松就可记录下put的顺序。还好这个map不太大,但是你的设计可以更好的啊。

建议:把map打散,LinkedList记录顺序,HashSet快速contain到key。
TreeMap按date排序,基本上能解决这个问题


 

 

Spring MVC如何防止重复提交?类似Struts Token机制!
2007-03-01 18:32

首先,需要将继承了SimpleFormController之类的sessionForm设为true。这样,在显示一个新表单时,Spring会将command存放在session中,而在提交表单时,Spring会从session中取出此command,随后立即从session中删除存放command的attribute。如果发现在session中没有command,Spring将其断定为重复提交,转而执行handleInvalidSubmit(request, response),可覆盖此方法负责防止重复提交的任务。可以这么说,当setSessionForm(true)之后,如果没有先后经历显示表单、提交表单的过程,就会被认为是重复提交表单。而有一些情况下却必须重复提交表单,如,修改数据库的数据后,试图写入数据库时因某些异常失败,如果此时异常被当前页面捕获并依旧返回当前页面,由于command已经被Spring在后台从session中移走,因此,就被认为是无效重复提交,从而导致第二次经修改后的记录无法正确提交到数据库中。handleInvalidSubmit()必须考虑到这种情况。

-------------------------------------------------------------------------------------------------

方法2

楼上提供的方法比较麻烦。
我在项目中使用过一种比较简单的方法,就是使用一个Filter,设置request的参数,使禁止Browser对页面进行缓存

0
2
分享到:
评论
5 楼 jinnianshilongnian 2012-11-03  
a52071453 写道
jinnianshilongnian 写道
1、Spring3.1的新的Flash Attributes(类似于2)
2、你说的token机制
3、重定向

其实就是SESSION 和 REQ 参数对比!其实重定向可以解决 重复提交 解决不了重复刷新

是的, 所以我一般使用3
4 楼 a52071453 2012-11-02  
次生成token
freezingsky 写道
token,用中文的说法,可以叫令牌。保证每一次的请求都是不同的令牌。在不采用任何框架的情况下,可以这简单的描述。在客户端,通过隐藏域安放一个token值,每次生成token值时,服务器端可以判断cache(自定义的缓存)中是否已经有一个值一样的token,有就认为重复提交,没有就认为是第一次提交,然后cache进去。
个人浅见!


对 必有有一个隐藏hidden 判断是不是前一个页面走过来的
3 楼 a52071453 2012-11-02  
jinnianshilongnian 写道
1、Spring3.1的新的Flash Attributes(类似于2)
2、你说的token机制
3、重定向

其实就是SESSION 和 REQ 参数对比!其实重定向可以解决 重复提交 解决不了重复刷新
2 楼 jinnianshilongnian 2012-10-31  
1、Spring3.1的新的Flash Attributes(类似于2)
2、你说的token机制
3、重定向
1 楼 freezingsky 2012-10-31  
token,用中文的说法,可以叫令牌。保证每一次的请求都是不同的令牌。在不采用任何框架的情况下,可以这简单的描述。在客户端,通过隐藏域安放一个token值,每次生成token值时,服务器端可以判断cache(自定义的缓存)中是否已经有一个值一样的token,有就认为重复提交,没有就认为是第一次提交,然后cache进去。
个人浅见!

相关推荐

Global site tag (gtag.js) - Google Analytics