SpringMVC之——防止重复提交表单的方法(一)

转载请注明出处:https://blog.csdn.net/l1028386804/article/details/80440853

这篇博文介绍第一种方法:判断session或其他缓存中保存的token,这里以session为例,具体大家也可以自行扩展以其他的缓存实现。

这种方式比较麻烦,每次在提交表单时都必须传入上次的token。而且当一个页面使用ajax时,多个表单提交就会有问题。

1、自定义注解FormToken

注解的作用主要是用来标识哪些类需要被拦截,处理防重复提交的问题,具体代码如下:

package io.mykit.filter.spring.repeat.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * 以Token注解形式方式重复提交内容
 * @author liuyazhuang
 *
 */
@Inherited
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FormToken {

	boolean save() default false;

	boolean remove() default false;
}

2、创建拦截器类FormTokenInterceptor

这个类主要是对标识了@FormToken的方法进行拦截,并且按照相应的规则进行处理,FormTokenInterceptor不进行具体的规则处理,具体规则交由子类实现。具体代码如下:

package io.mykit.filter.spring.repeat.interceptor;
import java.lang.reflect.Method;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import io.mykit.filter.spring.repeat.annotation.FormToken;

/**
 * 基于Token形式的防重复提交拦截器
 * @author liuyazhuang
 *
 */
public abstract class FormTokenInterceptor extends HandlerInterceptorAdapter {
	
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();
            FormToken annotation = method.getAnnotation(FormToken.class);
            if (annotation != null) {
                boolean needSaveSession = annotation.save();
                if (needSaveSession) {
                    request.getSession(false).setAttribute("formToken", UUID.randomUUID().toString());
                }
                boolean needRemoveSession = annotation.remove();
                if (needRemoveSession) {
                    if (isRepeatSubmit(request)) {
                        return false;
                    }
                    request.getSession(false).removeAttribute("formToken");
                }
            }
            return true;
        } else {
            return super.preHandle(request, response, handler);
        }
    }

    /**
     * 具体规则交由子类实现
     * @param request
     * @return
     */
    public abstract boolean isRepeatSubmit(HttpServletRequest request);
}

3、创建具体规则实现类MyFormTokenInterceptor

这个类继承FormTokenInterceptor类,实现isRepeatSubmit方法来提供具体的处理规则,这个类也是本例提供的处理方式,如果大家想用其他的处理方式,可自行定义处理类继承FormTokenInterceptor,实现isRepeatSubmit方法即可,这也体现了本实例的高可扩展性。具体代码如下:

package io.mykit.filter.spring.repeat.interceptor.impl;

import javax.servlet.http.HttpServletRequest;

import io.mykit.filter.spring.repeat.interceptor.FormTokenInterceptor;

/**
 * 具体规则的实现,这种方式页面需要添加
 * 
 * @author liuyazhuang
 *
 */
public class MyFormTokenInterceptor extends FormTokenInterceptor {
	
	@Override
	public boolean isRepeatSubmit(HttpServletRequest request) {
        String serverToken = (String) request.getSession(false).getAttribute("formToken");
        if (serverToken == null) {
            return true;
        }
        String clinetToken = request.getParameter("formToken");
        if (clinetToken == null) {
            return true;
        }
        if (!serverToken.equals(clinetToken)) {
            return true;
        }
        return false;
    }
}

4、配置springmvc-interceptor.xml文件



	
     
     
	     
		         
		         
	     
	     
     
     
  
 

5、具体使用

在相关的web工程中的springmvc配置文件中引入springmvc-interceptor.xml文件

如下:

当你自己继承FormTokenInterceptor类实现了具体的拦截规则时,就不能在相关的web工程中的springmvc配置文件中引入springmvc-interceptor.xml文件了,需要添加如下配置


     
	         
	         
     

然后在接口的方法上加上注解即可。在需要生成token的controller上增加@FormToken(save=true),而在需要检查重复提交的controller上添加@FormToken(remove=true)就可以了。

另外,你需要在view里在form里增加下面代码:

 
注意在ajax提交时 要加上 formToken参数

6、附上pom.xml依赖配置

 
    UTF-8
  
  
  
  	
      javax.servlet
      javax.servlet-api
      3.0.1
    
    
    
	    cglib
	    cglib
	    3.2.6
	
	
	
	    com.alibaba
	    fastjson
	    1.2.47
	
    
   
	    org.springframework
	    spring-expression
	    ${spring.version}
		
		
  		
		    org.springframework
		    spring-messaging
		    ${spring.version}
		
		
		
		    org.springframework
		    spring-jms
		    ${spring.version}
		
		
		
			org.springframework
			spring-aop
			${spring.version}
		
		
		
			org.springframework
			spring-jdbc
			 ${spring.version}
		
		
		 
            org.springframework
            spring-context
            ${spring.version}
        
	
		
		    org.springframework
		    spring-context-support
		    ${spring.version}
		
		
		
            org.springframework
            spring-web
            ${spring.version}
        
        
         
		    org.aspectj
		    aspectjtools
		    1.9.1
		
		
      
          org.springframework
          spring-webmvc
          ${spring.version}
      
  


你可能感兴趣的:(SpringMVC,J2EE)