`
baalwolf
  • 浏览: 343312 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Spring MVC拦截器+注解方式实现防止表单重复提交

 
阅读更多
原理:在新建页面中Session保存token随机码,当保存时验证,通过后删除,当再次点击保存时由于服务器端的Session中已经不存在了,所有无法验证通过。
 

1.新建注解:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
 * <p>
 * 防止重复提交注解,用于方法上<br/>
 * 在新建页面方法上,设置needSaveToken()为true,此时拦截器会在Session中保存一个token,
 * 同时需要在新建的页面中添加
 * <input type="hidden" name="token" value="${token}">
 * <br/>
 * 保存方法需要验证重复提交的,设置needRemoveToken为true
 * 此时会在拦截器中验证是否重复提交
 * </p>
 * @author: chuanli
 * @date: 2013-6-27上午11:14:02
 *
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AvoidDuplicateSubmission {
    boolean needSaveToken() default false;
    boolean needRemoveToken() default false;
}

 

 

2. 新建拦截器

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/**
 * <p>
 * 防止重复提交过滤器
 * </p>
 *
 * @author: chuanli
 * @date: 2013-6-27上午11:19:05
 */
public class AvoidDuplicateSubmissionInterceptor extends HandlerInterceptorAdapter {
    private static final Logger LOG = Logger.getLogger(AvoidDuplicateSubmissionInterceptor.class);
 
    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {
 
        User user = UserUtil.getUser();
        if (user != null) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();
 
            AvoidDuplicateSubmission annotation = method.getAnnotation(AvoidDuplicateSubmission.class);
            if (annotation != null) {
                boolean needSaveSession = annotation.needSaveToken();
                if (needSaveSession) {
                    request.getSession(false).setAttribute("token", TokenProcessor.getInstance().generateToken());
                }
 
                boolean needRemoveSession = annotation.needRemoveToken();
                if (needRemoveSession) {
                    if (isRepeatSubmit(request)) {
                        LOG.warn("please don't repeat submit,[user:" + user.getUsername() + ",url:"
                                + request.getServletPath() + "]");
                        return false;
                    }
                    request.getSession(false).removeAttribute("token");
                }
            }
        }
        return true;
    }
 
    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;
    }
 
}

 

 

3. 在Spring中配置

 

1
2
3
4
5
6
7
8
9
<bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
   <property name="interceptors">
      <list>
          <bean class="com.sohu.tv.crm.aop.UserLogInterceptor"/>
          <bean class="com.sohu.tv.crm.aop.AvoidDuplicateSubmissionInterceptor"/>
      </list>
   </property>
 
</bean>

 

 

4. 在相关方法中加入注解:

 

1
2
3
4
5
6
7
8
@RequestMapping("/save")
 @AvoidDuplicateSubmission(needRemoveToken = true)
    public synchronized ModelAndView save(ExecutionUnit unit, HttpServletRequest request, HttpServletResponse response)
            throws Exception {
 
@RequestMapping("/edit")
    @AvoidDuplicateSubmission(needSaveToken = true)
    public ModelAndView edit(Integer id, HttpServletRequest request) throws Exception {

 

5.在新建页面中加入
                <input type="hidden" name="token" value="${token}">
 
 
分享到:
评论

相关推荐

    Spring中文帮助文档

    13.4.3. 拦截器(HandlerInterceptor) 13.5. 视图与视图解析 13.5.1. 视图解析器(ViewResolver) 13.5.2. 视图解析链 13.5.3. 重定向(Rediret)到另一个视图 13.6. 本地化解析器 13.6.1. ...

    Spring API

    13.4.3. 拦截器(HandlerInterceptor) 13.5. 视图与视图解析 13.5.1. 视图解析器(ViewResolver) 13.5.2. 视图解析链 13.5.3. 重定向(Rediret)到另一个视图 13.6. 本地化解析器 13.6.1. ...

    Spring-Reference_zh_CN(Spring中文参考手册)

    13.4.3. 拦截器(HandlerInterceptor) 13.5. 视图与视图解析 13.5.1. 视图解析器 13.5.2. 视图解析链 13.5.3. 重定向(Rediret)到另一个视图 13.5.3.1. RedirectView 13.5.3.2. redirect:前缀 13.5.3.3. forward:...

    Spring 2.0 开发参考手册

    13.4.3. 拦截器(HandlerInterceptor) 13.5. 视图与视图解析 13.5.1. 视图解析器 13.5.2. 视图解析链 13.5.3. 重定向(Rediret)到另一个视图 13.6. 本地化解析器 13.6.1. AcceptHeaderLocaleResolver 13.6.2....

    Spring.3.x企业应用开发实战(完整版).part2

    15.7.2 装配拦截器 15.7.3 异常处理 15.8 小结 第5篇 测试及实战 第16章 实战型单元测试 16.1 单元测试概述 16.1.1 为什么需要单元测试 16.1.2 单元测试之误解 16.1.3 单元测试之困境 16.1.4 单元测试基本概念 16.2...

    spring chm文档

    13.4.3. 拦截器(HandlerInterceptor) 13.5. 视图与视图解析 13.5.1. 视图解析器 13.5.2. 视图解析链 13.5.3. 重定向(Rediret)到另一个视图 13.6. 本地化解析器 13.6.1. AcceptHeaderLocaleResolver 13.6.2....

    Spring攻略(第二版 中文高清版).part1

    8.3 用处理程序拦截器拦截请求 297 8.3.1 问题 297 8.3.2 解决方案 298 8.3.3 工作原理 298 8.4 解析用户区域 302 8.4.1 问题 302 8.4.2 解决方案 302 8.4.3 工作原理 302 8.5 外部化区分区域的...

    Struts2 in action中文版

    15.3 使用令牌防止表单重复提交 313 15.3.1 使用s:token/表单标签 313 15.3.2 令牌拦截器规则的例外 314 15.4 自动显示等待页面 316 15.5 完成CRUD操作的一个动作 317 15.5.1 CRUD 317 15.5.2 拦截器和接口 318 ...

    Spring3.x企业应用开发实战(完整版) part1

    15.7.2 装配拦截器 15.7.3 异常处理 15.8 小结 第5篇 测试及实战 第16章 实战型单元测试 16.1 单元测试概述 16.1.1 为什么需要单元测试 16.1.2 单元测试之误解 16.1.3 单元测试之困境 16.1.4 单元测试基本概念 16.2...

    Spring攻略(第二版 中文高清版).part2

    8.3 用处理程序拦截器拦截请求 297 8.3.1 问题 297 8.3.2 解决方案 298 8.3.3 工作原理 298 8.4 解析用户区域 302 8.4.1 问题 302 8.4.2 解决方案 302 8.4.3 工作原理 302 8.5 外部化区分区域的...

    Spring in Action(第二版 中文高清版).part2

    11.3.4 使用注释声明拦截器 11.4 小结 第12章 访问企业服务 12.1 从JNDI中获取对象 12.1.1 使用传统的JNDI 12.1.2 注入JNDI对象 12.1.3 在Spring 2中注入JNDI对象 12.2 发送电子邮件 12.2.1 配置邮件发送...

    Spring in Action(第二版 中文高清版).part1

    11.3.4 使用注释声明拦截器 11.4 小结 第12章 访问企业服务 12.1 从JNDI中获取对象 12.1.1 使用传统的JNDI 12.1.2 注入JNDI对象 12.1.3 在Spring 2中注入JNDI对象 12.2 发送电子邮件 12.2.1 配置邮件发送...

    SpringMVC Employee Demo

    内容:本次实践内容包括...通过超链接切换中英文、文件上传、自定义的拦截器、拦截器的零Xml配置、异常处理(ExceptionHandler注解、ResponseStatusExceptionResolver、SimpleMappingExceptionResolver)等

    Java学习笔记-个人整理的

    {1.2}数字表达方式}{17}{section.1.2} {1.3}补码}{19}{section.1.3} {1.3.1}总结}{23}{subsection.1.3.1} {1.4}数据类型}{23}{section.1.4} {1.4.1}整数与浮点数}{23}{subsection.1.4.1} {1.4.1.1}浮点数原理}...

    JBoss Seam 工作原理、seam和hibernate的范例、RESTFul的seam、seam-gen起步、seam组件、配置组件、jsf,jboss、标签、PDF、注解等等

    Seam - 语境相关的组件[满江红20071230]............................................................................................................................ 1 Java EE 框架...........................

Global site tag (gtag.js) - Google Analytics