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

注,如果是集群的方式,则需要将token放入到缓存中即可。 

注解Token代码:java源码  

Java代码 复制代码 收藏代码
.@Target(ElementType.METHOD)
.@Retention (RetentionPolicy.RUNTIME)
.public @interface Token {
.
. boolean needSaveToken () default false ;
.
. boolean needRemoveToken () default false ;
.} 拦截器TokenInterceptor代码: Java代码 复制代码 收藏代码
.public class TokenInterceptor extends HandlerInterceptorAdapter {
.
. @Override
. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throwsException {
. 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的配置文件里加入: Xml代码 复制代码 收藏代码
.<!-- 拦截器配置 -->
.< mvc:interceptors >
. <!-- 配置Shiro拦截器,实现注册用户的注入 -->
. < mvc:interceptor >
. < mvc:mapping path = "/**" />
. < bean class = "com.storezhang.video.shiro.ShiroInterceptor" />
. </ mvc:interceptor >
. <!-- 配置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里增加下面代码: Html代码 复制代码 收藏代码
.< input type = "hidden" name = "token" value = "${token}" /> 在相关方法中加入注解 Java代码 复制代码 收藏代码
.@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 { 已经完成了,去试试看你的数据还能重复提交了吧。

Spring MVC拦截器+注解方式实现防止表单重复提交的更多相关文章

  1. spring boot 学习(七)小工具篇:表单重复提交

    注解 + 拦截器:解决表单重复提交 前言 学习 Spring Boot 中,我想将我在项目中添加几个我在 SpringMVC 框架中常用的工具类(主要都是涉及到 Spring AOP 部分知识).比如 ...

  2. Spring MVC实现防止表单重复提交(转)

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

  3. 写的太细了!Spring MVC拦截器的应用,建议收藏再看!

    Spring MVC拦截器 拦截器是Spring MVC中强大的控件,它可以在进入处理器之前做一些操作,或者在处理器完成后进行操作,甚至是在渲染视图后进行操作. 拦截器概述 对于任何优秀的MVC框架, ...

  4. SSM(spring mvc+spring+mybatis)学习路径——2-2、spring MVC拦截器

    目录 2-2 Spring MVC拦截器 第一章 概述 第二章 Spring mvc拦截器的实现 2-1 拦截器的工作原理 2-2 拦截器的实现 2-3 拦截器的方法介绍 2-4 多个拦截器应用 2- ...

  5. spring mvc 拦截器的使用

    Spring MVC 拦截器的使用 拦截器简介 Spring MVC 中的拦截器(Interceptor)类似于 Servler 中的过滤器(Filter).用于对处理器进行预处理和后处理.常用于日志 ...

  6. Spring Boot 2.X(九):Spring MVC - 拦截器(Interceptor)

    拦截器 1.简介 Spring MVC 中的拦截器(Interceptor)类似于 Servlet 开发中的过滤器 Filter,它主要用于拦截用户请求并作相应的处理,它也是 AOP 编程思想的体现, ...

  7. Spring MVC拦截器浅析

    Spring MVC拦截器 重点:Spring MVC的拦截器只会拦截控制器的请求,如果是jsp.js.image.html则会放行. 什么是拦截器 运行在服务器的程序,先于Servlet或JSP之前 ...

  8. Spring MVC 中采用注解方式 Action中跳转到另一个Action的写法

    Spring MVC 中采用注解方式 Action中跳转到另一个Action的写法 在Action中方法的返回值都是字符串行,一般情况是返回某个JSP,如: return "xx" ...

  9. 【Java Web开发学习】Spring MVC 拦截器HandlerInterceptor

    [Java Web开发学习]Spring MVC 拦截器HandlerInterceptor 转载:https://www.cnblogs.com/yangchongxing/p/9324119.ht ...

随机推荐

  1. jsonp协议原理深度解析

    前言 今天在开发联调的过程中,需要跨域的获取数据,因为使用的jquery,当然使用dataType:'jsonp'就能够很easy的解决了.但是因为当时后端没有支持jsonp来访问,后来他在实现这个功 ...

  2. Cloud Design Patterns: Prescriptive Architecture Guidance for Cloud Applications 云设计模式:云应用的规范架构指导

    1.Cache-aside Pattern 缓存模式 Load data on demand into a cache from a data store. This pattern can impr ...

  3. 记录visual Studio使用过程中的两个问题

    Visual Studio是Windows平台下进行项目管理和开发的终极利器.除了微软自家的技术外,新版的VS不但支持Javascript, Python的开发调试,甚至还支持了Android, iO ...

  4. WCF学习系列四--【WCF Interview Questions – Part 4 翻译系列】

    WCF Interview Questions – Part 4   This WCF service tutorial is part-4 in series of WCF Interview Qu ...

  5. 【原创】Kafka console consumer源代码分析(一)

    上一篇中分析了Scala版的console producer代码,这篇文章为读者带来一篇console consumer工作原理分析的随笔.其实不论是哪个consumer,大部分的工作原理都是类似的. ...

  6. ASP.NET MVC使用Areas后怎样获取Area(区域)的名称

    写此随笔,目的只为今后在ASP.NET MVC项目中再用到Area(区域)时作为备查. 获取当前Area(区域)名称的方法是: ViewContext.RouteData.DataTokens[&qu ...

  7. .net登录的一般模式

    思路: 1.检查登录: private string CheckLogin(HttpContext context) { Model.TUser model = (Model.TUser)contex ...

  8. SQL Server 数据库分离与附加

    一.概述 SQL Server提供了“分离/附加”数据库.“备份/还原”数据库.复制数据库等多种数据库的备份和恢复方法.这里介绍一种学习中常用的“分离/附加”方法,类似于大家熟悉的“文件拷贝”方法,即 ...

  9. STL中vector、list、map、set区别(转载)

    list封装了链表,vector封装了数组, list和vector得最主要的区别在于vector使用连续内存存储的,他支持[]运算符,而list是以链表形式实现的,不支持[].vector对于随机访 ...

  10. Hibernate-chapter two

    又见面啦!!!经过上一章的学习,我们大概对Hibernate框架有所了解.接下来进入我们的第二阶段——实战! ======准备数据库====== 这里使用MySQL作为示范. 创建一个名为Hibern ...