注解的一些基础:

参见http://blog.csdn.net/duo2005duo/article/details/50505884和

http://blog.csdn.net/duo2005duo/article/details/50511476这两篇文章

1,自定义一个注解@Token 用来标记需要防止重复提交的方法

  1. package com.bjca.framework.util;
  2. /**
  3. * <p>
  4. *关于这个方法的用法是:
  5. *在需要生成token的controller上增加@Token(save=true),
  6. *而在需要检查重复提交的controller上添加@Token(remove=true)就可以了
  7. *另外,你需要在view里在form里增加下面代码:
  8. *<input type="hidden" name="token" value="${token}">
  9. * 此时会在拦截器中验证是否重复提交
  10. * </p>
  11. *
  12. */
  13. import java.lang.annotation.*;
  14.  
  15. @Target(ElementType.METHOD)
  16. @Retention (RetentionPolicy.RUNTIME)
  17. public @interface Token {
  18.  
  19. boolean save() default false ;
  20.  
  21. boolean remove() default false ;
  22. }

2,自定义一个针对该注解的拦截器 TokenInterceptor

  1. package com.bjca.framework.util;
  2.  
  3. import org.apache.commons.logging.Log;
  4. import org.apache.commons.logging.LogFactory;
  5. import org.springframework.web.method.HandlerMethod;
  6. import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
  7.  
  8. import javax.servlet.http.HttpServletRequest;
  9. import javax.servlet.http.HttpServletResponse;
  10. import java.lang.reflect.Method;
  11. import java.util.UUID;
  12.  
  13. public class TokenInterceptor extends HandlerInterceptorAdapter {
  14. public static Log log = LogFactory.getLog(TokenInterceptor.class);
  15. @Override
  16. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  17. System.out.println(handler.getClass());
  18. if (handler instanceof HandlerMethod) {
  19. HandlerMethod handlerMethod = (HandlerMethod) handler;
  20. Method method = handlerMethod.getMethod();
  21. Token annotation = method.getAnnotation(Token. class );
  22.  
  23. if (annotation != null ) {
  24. boolean needSaveSession = annotation.save();
  25. if (needSaveSession) {
  26. String uuid=UUID.randomUUID().toString();
  27. log.debug("提交生成除令牌"+uuid);
  28. request.getSession( false ).setAttribute( "token" , uuid);
  29. }
  30. boolean needRemoveSession = annotation.remove();
  31. if (needRemoveSession) {
  32. if (isRepeatSubmit(request)) {
  33. return false ;
  34. }
  35. log.debug("提交移除令牌"+request.getSession().getAttribute("token" ));
  36. request.getSession( false ).removeAttribute( "token" );
  37. }
  38. }
  39. return true ;
  40. } else {
  41. return super .preHandle(request, response, handler);
  42. }
  43. }
  44.  
  45. private boolean isRepeatSubmit(HttpServletRequest request) {
  46. String serverToken = (String) request.getSession( false ).getAttribute( "token" );
  47. if (serverToken == null ) {
  48. return true ;
  49. }
  50. String clinetToken = request.getParameter( "token" );
  51. if (clinetToken == null ) {
  52. return true ;
  53. }
  54. if (!serverToken.equals(clinetToken)) {
  55. return true ;
  56. }
  57. return false ;
  58. }
  59. }

3,在spring MVC的配置文件里注册该拦截器

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:mvc="http://www.springframework.org/schema/mvc"
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5. xmlns:p="http://www.springframework.org/schema/p"
  6. xmlns:context="http://www.springframework.org/schema/context"
  7. xsi:schemaLocation="http://www.springframework.org/schema/beans
  8. http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
  9. http://www.springframework.org/schema/context
  10. http://www.springframework.org/schema/context/spring-context-4.0.xsd
  11. http://www.springframework.org/schema/mvc
  12. http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd"
  13. >
  14. <!-- 对spring org.lxh包下所有注解扫描 -->
  15. <context:component-scan base-package="com.xxx">
  16. <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository" />
  17. </context:component-scan>
  18. <!-- 支持spring mvc新的注解类型 详细spring3.0手册 15.12.1 mvc:annotation-driven-->
  19. <mvc:annotation-driven />
  20.  
  21. <bean id="viewResolver"
  22. class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  23. <!-- 为了使用JSTL Tag修改默认的viewClass属性 -->
  24. <property
  25. name="viewClass"
  26. value="org.springframework.web.servlet.view.JstlView" />
  27. <property
  28. name="prefix"
  29. value="/WEB-INF/views/" />
  30. <property
  31. name="suffix"
  32. value=".jsp"></property>
  33. <property
  34. name="order"
  35. value="1"></property>
  36. </bean>
  37. <!-- 拦截器 -->
  38. <mvc:interceptors>
  39. <!-- 用户登录拦截 -->
  40. <bean class="com.xx.xxx.filter.StageSecurityInterceptor">
  41. <property name="patterns" >
  42. <list>
  43. <value>.*/console/.*\.jhtml</value>
  44. <value>.*/center/.*\.jhtml</value>
  45.  
  46. </list>
  47. </property>
  48. <property name="loginView">
  49. <value>/manage.jsp</value>
  50. </property>
  51. </bean>
  52. 54 <!-- 配置Token拦截器,防止用户重复提交数据 -->
  53. 55 <mvc:interceptor>
  54. 56 <mvc:mapping path="/**"/>
  55. 57 <bean class="com.xxx.framework.util.TokenInterceptor"/>
  56. 58 </mvc:interceptor>
  57. </mvc:interceptors>
  58. <!--
  59. <bean id="viewResolver"
  60. class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
  61. <property name="basenames">
  62. <list>
  63. <value>views-stage</value>
  64. </list>
  65. </property>
  66. </bean>
  67. -->
  68. </beans>

4,演示demo

4.1,在跳转至某个需要加上@Token(save = true)

  1. 1 @RequestMapping("/personalForm.jhtml")
  2. 2   @Token(save = true)
  3. public String personalForm(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) {
  4. Account account = Account.sessionAccount();
  5. if (account == null) {
  6. return "redirect:/login.jsp";
  7. }
  8.   //..........业务..............
  9.   }

4.2,在上个Controller 跳转的方法上加入${Token}

  1. <div class="main clearfix nav center regist copyright_main5">
  2. <h3 class="registTitle">填写身份信息</h3>
  3. <img alt="" src="<c:url value='/platform/stage/image/regist/wave.png'/>"><br /> <img src="<c:url value='/platform/stage/image/portals/regist-info.png'/>"></img>
  4. <c:if test="${personalInfoForm.checkState eq 2}">
  5. <br/>
  6. <div>
  7. <font color="red" size="2"><span>身份认证意见:${personalInfoForm.checkOpnion}</span></font>
  8. </div>
  9. </c:if>
  10. <form autocomplete="off" style="margin: 0;" id="form1" method="post" name="personalInfoForm" action="<c:url value='/center/member/savePersonalInfo.jhtml'/>" enctype="multipart/form-data">
  11. <input type="hidden" value="${personalInfoForm.id}" name="id" />
  12. <input type="hidden" name="token" value="${token}">

4.3,在表单提交方法的地方加上注解 @Token(remove = true)

  1. @RequestMapping(value = "/savePersonalInfo.jhtml", method = {RequestMethod.POST})
  2. @Token(remove = true)
  3. public String savePersonalInfo(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap, PersonalInfo personalInfoForm) throws Exception {
  4. DateFormat fm = new SimpleDateFormat("yyyy-MM-dd");
  5. Date birthday = fm.parse(request.getParameter("birthday2"));
  6. personalInfoForm.setBirthday(birthday);
  7.  
  8. Account account = Account.sessionAccount();
  9. if(account==null){
  10. return "redirect:/login.jsp";
  11. }
  12. //.....................业务.........................
  13. }

5,完成了。

Token注解防止表单的重复提交的更多相关文章

  1. 使用aop注解实现表单防重复提交功能

    原文:https://www.cnblogs.com/manliu/articles/5983888.html 1.这里采用的方法是:使用get请求进入表单页面时,后台会生成一个tokrn_flag分 ...

  2. Spring MVC表单防重复提交

    利用Spring MVC的过滤器及token传递验证来实现表单防重复提交. 创建注解 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RU ...

  3. struts2 文件的上传下载 表单的重复提交 自定义拦截器

    文件上传中表单的准备 要想使用 HTML 表单上传一个或多个文件 须把 HTML 表单的 enctype 属性设置为 multipart/form-data 须把 HTML 表单的method 属性设 ...

  4. Session机制三(表单的重复提交)

    1.表单的重复提交的情况 在表单提交到一个servlet,而servlet又通过请求转发的方式响应了一个JSP页面,这个时候地址栏还保留这servlet的那个路径,在响应页面点击刷新. 在响应页面没有 ...

  5. HttpSession解决表单的重复提交

    1). 重复提交的情况: ①. 在表单提交到一个 Servlet, 而 Servlet 又通过请求转发的方式响应一个 JSP(HTML) 页面, 此时地址栏还保留着 Serlvet 的那个路径, 在响 ...

  6. Struts2 - 表单的重复提交问题

    用户重复提交表单在某些场合将会造成非常严重的后果.例如,在使用信用卡进行在线支付的时候,如果服务器的响应速度太慢,用户有可能会多次点击提交按钮,而这可能导致那张信用卡上的金额被消费了多次.因此,重复提 ...

  7. HttpSession之表单的重复提交 & 验证码

    如果采用 HttpServletResponse.sendRedirct() 方法将客户端重定向到成功页面,将不会出现重复提交问题 1.表单的重复提交 1). 重复提交的情况: ①. 在表单提交到一个 ...

  8. php中如何防止表单的重复提交

    在php中如何防止表单的重复提交?其实也有几种解决方法. 下面小编就为大家介绍一下吧.需要的朋友可以过来参考下 代码: <?php /* * php中如何防止表单的重复提交 * by www.j ...

  9. php-- 避免表单的重复提交

    用户提交表单时可能因为网速的原因,或者网页被恶意刷新,致使同一条记录重复插入到数据库中,这是一个比较棘手的问题.我们可以从客户端和服务器端一起着手,设法避免同一表单的重复提交. 1.使用客户端脚本 提 ...

随机推荐

  1. 使用response实现文件下载功能

    response.setContentType("text/html;charset=utf-8");  response.setCharacterEncoding("u ...

  2. UML基础概念

    UML概述 uml简介 uml(unified Modeling Language )为面向对象软件设计提供统一的.标准的.可视化的建模语言.适用于描述以用例为驱动,以体系结构为中心的软件设计的全过程 ...

  3. 求解轨道力学二体意义下的Lambert方程(兰伯特方程)的Fortran程序

    轨道力学中二体问题下求解兰伯特方程. 老外写的Matlab程序,我把它转成了Fortran程序. !************************************************** ...

  4. strlen与sizeof有什么区别?

    其实二者的区别还是很大的,首先strlen计算的长度不包括字符串最后的终止null字节, 而sizeof则计算包括终止null的缓冲区长度.还有一点很容易被忽略,strlen需要一次函数调用, 即它是 ...

  5. poj 2184(dp变形,进一步加深01背包)

    点击打开链接 题意: 给你n个物品,每个物品都有两个属性,s和f,要求选择一些物品,使sum(s)+sum(f)最大,并且sum(s)>=0&&sum(f)>=0, 根据0 ...

  6. Python网络爬虫

    http://blog.csdn.net/pi9nc/article/details/9734437 一.网络爬虫的定义 网络爬虫,即Web Spider,是一个很形象的名字. 把互联网比喻成一个蜘蛛 ...

  7. SQL Server跨网段(跨机房)FTP复制

    SQL Server跨网段(跨机房)FTP复制 2013-09-24 17:53 by 听风吹雨, 273 阅读, 0 评论, 收藏, 编辑 一. 背景 搭建SQL Server复制的时候,如果网络环 ...

  8. MVC常见的控制器,接口,数据层之间的操作

    user_books_info 类 namespace CiWong.LearningLevel.Mapping { public class user_books_info { /// <su ...

  9. 系统架构、网络通信、IM、视频会议技术

    专注于系统架构.网络通信.IM.视频会议技术. 主要作品: ESFramework 强悍的通信框架.P2P框架.群集平台. OMCS 简单易用的 网络语音视频 框架. MFile 语音视频录制组件. ...

  10. 异常信息:java.lang.OutOfMemoryError: PermGen space

    修改TOMCAT_HOME/bin/catalina.sh 在"echo "Using CATALINA_BASE:    $CATALINA_BASE""上面 ...