SpringMVC拦截器实现防重复提交

防重复提交在前端和后端都需要控制:
  前端:点击按钮后将按钮置灰不可用
  后端:采用自定义拦截器的方式,模拟Token实现原理

自定义拦截器实现以下防重原理:
1.初始化页面时生成一个唯一ID,将其放在页面隐藏域和session中
2.拦截器拦截请求,校验来自页面请求中的唯一ID与session中的ID是否一致
3.判断,如果一致则提交成功并移除session中的ID,不一致则说明重复提交并记录日志

一、自定义注解

package com.test.sub.repeatsubmit;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Token {
	
	boolean save() default false;
	boolean remove() default false;
	
}

二、自定拦截器

package com.test.sub.repeatsubmit;

import java.lang.reflect.Method;
import java.util.UUID;

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

import org.apache.log4j.Logger;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

public class RepeatSubmitInterceptor  extends HandlerInterceptorAdapter{
	
	private static final Logger log = Logger.getLogger(RepeatSubmitInterceptor.class);
	
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
		throws Exception {
		HandlerMethod handlerMethod = null;
		try {
			handlerMethod = (HandlerMethod)handler;
		} catch (Exception e) {
			return true;
		}
		Method method = handlerMethod.getMethod();
		
		Token token = method.getAnnotation(Token.class);
		if(token != null ){
			boolean saveSession = token.save();
			if(saveSession){
				request.getSession(true).setAttribute("token", UUID.randomUUID());
			}
			
			boolean removeSession = token.remove();
			if(removeSession){
				if(isRepeatSubmitSession(request)){
					log.info("repeat submit session :"+request.getServletPath());
					return false;
				}
				request.getSession(true).removeAttribute("token");
			}
		}
		return true;
	}
	
	private boolean isRepeatSubmitSession(HttpServletRequest request){
		String sessionToken = String.valueOf(request.getSession(true).getAttribute("token"));
		String clientToken =  String.valueOf(request.getParameter("token"));
		if(sessionToken == null || sessionToken.equals("")){
			return true;
		}
		if(clientToken == null || clientToken.equals("")){
			return true;
		}
		if(!sessionToken.equals(clientToken)){
			return true;
		}
		return false;
	}

}

三、初始化加载防重页面,生成唯一ID(代码片段)

/**
 * 打开新增或修改页面
 * @return
 */
@RequestMapping("showAddPage")
@Token(save=true)
public String showPlanAddPage(String rowId,int param,Model model) {...}

四、页面隐藏域保存ID 或者 ajax提交时加入ID



var data=encodeURI("name="+$('#name').val()+"&token=${token}");
$.ajax({
   type: "POST",
   async:true,
   url: "${rootPath}/iminventoryplan/save",
   data:data,
   success: function(msg){
    if(msg.result == 'true' || msg.result == true) {
 	$.messager.alert('提示',msg.msg,'info');
	goBack(1);
	}
    else {
	$.messager.alert('提示',msg.msg,'error');
	$('#appsave').linkbutton('enable');
	goBack(1);
	}
    }
});

五、需要防重校验的方法

/**
* 保存新增或修改的记录,将其持久化到数据库中
* @return
*/
@RequestMapping("/save")
@ResponseBody
@Token(remove=true)
public Map saveTkiminventoryplanInfo(HttpServletRequest request){...}

六、Spring加入拦截器配置


	
	
	


你可能感兴趣的:(JAVA)