SpringMVC 防止表單提交的解決方案

在平時開發中,若是網速比較慢的狀況下, 用戶提交表單後,發現服務器半天沒有響應,用戶可能覺得是本身沒有提交表單,就會再點擊提交按鈕重複提交表單,因此在開發中咱們須要防止表單重複提交javascript


1.表單重複提交的場景:

  • 在網絡延遲的狀況下讓用戶有時間點擊屢次submit致使表單重複提交html

  • 表單提交後用戶點擊 刷新按鈕致使表單重複提交java

  • 用戶提交表單後,點擊後退按鈕回退到表單頁面後進行再次提交spring


2.防止表單重複提交的方法

利用javascript防止表單重複提交

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML>
<html>
  <head>
    <title>Form表單</title>
        <script type="text/javascript">
        var isCommitted = false;//表單是否已經提交標識,默認爲false
        function dosubmit(){
            if(isCommitted==false){
                isCommitted = true;//提交表單後,將表單是否已經提交標識設置爲true
                return true;//返回true讓表單正常提交
            }else{
                return false;//返回false那麼表單將不提交
            }
        }
    </script>
  </head>
  
  <body>
      <form action="${pageContext.request.contextPath}/servlet/DoFormServlet" onsubmit="return dosubmit()" method="post">
        用戶名:<input type="text" name="username">
        <input type="submit" value="提交" id="submit">
    </form>
  </body>
</html>


表單提交後, 將提交按鈕設置爲disable 

代碼以下:服務器

function dosubmit(){
    //獲取表單提交按鈕
    var btnSubmit = document.getElementById("submit");
    //將表單提交按鈕設置爲不可用,這樣就能夠避免用戶再次點擊提交按鈕
    btnSubmit.disabled= "disabled";
    //返回true讓表單能夠正常提交
    return true;
}


利用Token的方式防止表單重複提交

在服務器端生成一個惟一的隨機標識號,稱爲Token(令牌),同時在當前用戶的Session域中保存這個Token。而後將Token發送到客戶端的Form表單中,在Form表單中使用隱藏域來存儲這個Token,表單提交的時候連同這個Token一塊兒提交到服務器端,而後在服務器端判斷客戶端提交上來的Token與服務器端生成的Token是否一致,若是不一致,那就是重複提交了,此時服務器端就能夠不處理重複提交的表單。若是相同則處理表單提交,處理完後清除當前用戶的Session域中存儲的標識號。網絡


3.SpringMVC防止表單重複提交

定義Token代碼:mvc

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Token {

    boolean save() default false;
    boolean remove() default false;
}

定義攔截器TokenInterceptor:app

public class TokenInterceptor 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();
            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 clientToken = request.getParameter("token");
        if (clientToken == null) {
            return true;
        }

        if(!serverToken.equals(clientToken)){
            return true;
        }

        return false;
    }
}


而後在springmvc的配置文件中加入:dom

<!--配置攔截器-->
<mvc:interceptors>
       <!--配置token攔截器,防止用戶重複提交數據-->
       <mvc:interceptor>
              <mvc:mapping path="/**"/>
              <bean class="com.simple.interceptor.TokenInterceptor"/>
       </mvc:interceptor>
</mvc:interceptors>


在jsp頁面form裏面添加下面的代碼:jsp

<input type="hidden" name="token" value="${token}">


使用上面在須要生成token的controller上增長@Token(save=true) ,須要檢查重複提交的controller上添加@Token(remove=true)

@RequestMapping("/save")
 @AvoidDuplicateSubmission(save= true)
    public synchronized ModelAndView save(ExecutionUnit unit, HttpServletRequest request, HttpServletResponse response)
            throws Exception {
 
@RequestMapping("/edit")
    @AvoidDuplicateSubmission(remove= true)
    public ModelAndView edit(Integer id, HttpServletRequest request) throws Exception {
相關文章
相關標籤/搜索