Spring MVC防止数据重复提交

         下面来讲一下如何在Spring MVC里面解决此问题(其它框架也一样,逻辑一样,思想一样,和具体框架没什么关系)。要解决重复提交,有很多办法,比如说在提交完成后redirect一下,也可以用本文提到的使用token的方法(我不使用redirect是因为那样解决不了ajax提交数据或者移动应用提交数据,另一个原因是现在比较通行的方法是使用token,像python里的django框架也是使用token来解决)。

使用token的逻辑是,给所有的url加一个拦截器,在拦截器里面用java的UUID生成一个随机的UUID并把这个UUID放到session里面,然后在浏览器做数据提交的时候将此UUID提交到服务器。服务器在接收到此UUID后,检查一下该UUID是否已经被提交,如果已经被提交,则不让逻辑继续执行下去…

注解Token代码:

package com.mgear.samering.interceptor;

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

/**
 * <p>
 * 防止重复提交注解,用于方法上<br/>
 * 在新建页面方法上,设置needSaveToken()为true,此时拦截器会在Session中保存一个token,
 * 同时需要在新建的页面中添加
 * <input type="hidden" name="token" value="${token}">
 * <br/>
 * 保存方法需要验证重复提交的,设置needRemoveToken为true
 * 此时会在拦截器中验证是否重复提交
 * </p>
 * 
 *
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AvoidDuplicateSubmission {
    boolean needSaveToken() default false;
    boolean needRemoveToken() default false;
}


package com.mgear.samering.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;



/**
 * <p>
 * 防止重复提交过滤器
 * </p>
 *
 * 
 */
public class AvoidDuplicateSubmissionInterceptor extends HandlerInterceptorAdapter {
 
    @Override
    public boolean preHandle(HttpServletRequest request,
            HttpServletResponse response, Object handler) throws Exception {
            HandlerMethod handlerMethod ;
            if (handler instanceof HandlerMethod) {
            	handlerMethod = (HandlerMethod) handler;
            	} else {
            	return true;
            }
            Method method = handlerMethod.getMethod();
            AvoidDuplicateSubmission annotation = method.getAnnotation(AvoidDuplicateSubmission.class);
            if (annotation != null) {
                boolean needSaveSession = annotation.needSaveToken();
                if (needSaveSession) {
                    request.getSession(false).setAttribute("token",UUID.randomUUID().toString());
                }
 
                boolean needRemoveSession = annotation.needRemoveToken();
                if (needRemoveSession) {
                    if (isRepeatSubmit(request)) {
                        return false;
                    }
                    request.getSession(false).removeAttribute("token");
                }
            }
        return true;
    }
 
    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的配置文件里加入:

<!-- 设置重复提交校验 -->
		<mvc:interceptor>
			<mvc:mapping path="/**"/>
			<mvc:exclude-mapping path="/common/**"/>
			<bean class="com.mgear.samering.interceptor.AvoidDuplicateSubmissionInterceptor"/>
		</mvc:interceptor>
		<mvc:interceptor>
			<mvc:mapping path="/**"/>
			<mvc:exclude-mapping path="/login/**"/>
			<mvc:exclude-mapping path="/common/**"/>
			<mvc:exclude-mapping path="/register/**"/>
			<bean class="com.mgear.samering.interceptor.CheckLoginInterceptor"/>
		</mvc:interceptor>
	</mvc:interceptors>

在相关方法中加入注解:

                @RequestMapping("/getRecommend_Info")
	        @AvoidDuplicateSubmission(needSaveToken = true)
		public String getRecommend_Info(String ApplyId,Model model,HttpSession session){
             @RequestMapping("/Recommend_save")
	     @AvoidDuplicateSubmission(needRemoveToken = true)
	    public @ResponseBody JSONObject Recommend_save(String json,HttpServletRequest request){

在页面中加入

                <input type="hidden" name="token" value="${token}">,ajax提交的时候,将这个也提交


发布了56 篇原创文章 · 获赞 7 · 访问量 14万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章