注解的一些基础:

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

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

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

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

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

 package com.bjca.framework.util;

 import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;
import java.util.UUID; public class TokenInterceptor extends HandlerInterceptorAdapter {
public static Log log = LogFactory.getLog(TokenInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println(handler.getClass());
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) {
String uuid=UUID.randomUUID().toString();
log.debug("提交生成除令牌"+uuid);
request.getSession( false ).setAttribute( "token" , uuid);
}
boolean needRemoveSession = annotation.remove();
if (needRemoveSession) {
if (isRepeatSubmit(request)) {
return false ;
}
log.debug("提交移除令牌"+request.getSession().getAttribute("token" ));
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 ;
}
}

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

 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd"
>
<!-- 对spring org.lxh包下所有注解扫描 -->
<context:component-scan base-package="com.xxx">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository" />
</context:component-scan>
<!-- 支持spring mvc新的注解类型 详细spring3.0手册 15.12.1 mvc:annotation-driven-->
<mvc:annotation-driven /> <bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 为了使用JSTL Tag修改默认的viewClass属性 -->
<property
name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property
name="prefix"
value="/WEB-INF/views/" />
<property
name="suffix"
value=".jsp"></property>
<property
name="order"
value="1"></property>
</bean>
<!-- 拦截器 -->
<mvc:interceptors>
<!-- 用户登录拦截 -->
<bean class="com.xx.xxx.filter.StageSecurityInterceptor">
<property name="patterns" >
<list>
<value>.*/console/.*\.jhtml</value>
<value>.*/center/.*\.jhtml</value> </list>
</property>
<property name="loginView">
<value>/manage.jsp</value>
</property>
</bean>
54 <!-- 配置Token拦截器,防止用户重复提交数据 -->
55 <mvc:interceptor>
56 <mvc:mapping path="/**"/>
57 <bean class="com.xxx.framework.util.TokenInterceptor"/>
58 </mvc:interceptor>
</mvc:interceptors>
<!--
<bean id="viewResolver"
class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
<property name="basenames">
<list>
<value>views-stage</value>
</list>
</property>
</bean>
-->
</beans>

4,演示demo

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

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

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

 <div class="main clearfix nav center regist copyright_main5">
<h3 class="registTitle">填写身份信息</h3>
<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>
<c:if test="${personalInfoForm.checkState eq 2}">
<br/>
<div>
<font color="red" size="2"><span>身份认证意见:${personalInfoForm.checkOpnion}</span></font>
</div>
</c:if>
<form autocomplete="off" style="margin: 0;" id="form1" method="post" name="personalInfoForm" action="<c:url value='/center/member/savePersonalInfo.jhtml'/>" enctype="multipart/form-data">
<input type="hidden" value="${personalInfoForm.id}" name="id" />
<input type="hidden" name="token" value="${token}">

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

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

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. Windows注册表的基本知识及应用

    转帖:Windows注册表的基本知识及应用 2009-12-23 11:30:56 分类: Windows注册表的基本知识及应用  一.注册表的重要性 在DOS年代,对计算机的内存管理及系统配置主要通 ...

  2. DBMS_LOB包的使用

    DBMS_LOB包的使用 1.  dbms_lob.append( dest_lob  IN  OUT  NOCOPY  BLOB, src_lob  IN  BLOB) dbms_lob.appen ...

  3. win7 64位下如何安装配置mysql-5.7.7-rc-winx64

    距离上次安装MySQL已经过去好久了.步骤这些,有可能会忘记.简单记录一下吧.(参考了一些网络上的博客.) 1.mysql-5.7.5-m15-winx64.zip下载 官方网站下载地址: http: ...

  4. C++ Builder中splitter控件的使用方法简介

    C++ Builder提供了一个Splitter控件来实现对用户窗口的分割,只需拖动该控件到窗体上,就可以实现窗口的任意分割.把面板控件(Panel)拖动到窗体上,设置其对齐方式,然后把Splitte ...

  5. MVC 5 - 查询Details和Delete方法

    MVC 5 - 查询Details和Delete方法 在这部分教程中,接下来我们将讨论自动生成的Details和Delete方法. 查询Details和Delete方法 打开Movie控制器并查看De ...

  6. Jenkins Slave 设置

    Jenkins Slave node环境变量设置有很多trap,在最近的工作当中,我把slave部署在red hat linux 上,进行c++项目的编译部署和发布,但是在执行工程的时候,总会报出某些 ...

  7. Dynamics CRM不发布JS调试

    本博客已迁移至   http://www.krely.cn/ 上个项目做了一年多,大多是在做JS的开发,由于开发人数比较多,着实被坑的不轻.因为JS修改完成之后必须要发布,对于我们动辄几千行的JS的调 ...

  8. Code First 启用迁移时出错 HRESULT:0x80131040

    问题:Enable-Migrations 使用“8”个参数调用“CreateInstanceFrom”时发生异常 (异常来自 HRESULT:0x80131040) PM> Enable-Mig ...

  9. 使用VS2010命令提示窗口操作程序集强命名

    说明:文中示例均以将文件置于D盘根目录(D:\)下为例. 一.查看程序集是否具有强命名 sn -T d:\LicBase.dll 若有则会显示PublicKeyToken值,反之不会. 二.给无强命名 ...

  10. [转]How WebKit’s Event Model Works

    原文:https://homes.cs.washington.edu/~burg/projects/timelapse/articles/webkit-event-implementation/ Fi ...