有兩種防止重複提交:javascript
咱們能夠在函數調用HTTP請求以前禁用提交按鈕,並在完成HTTP響應後再次啓用它。該技術對於須要很長時間才能完成的過程(超過5秒)是有效的。因爲不耐煩而沒法得到結果,用戶沒法再次單擊n'。此外,咱們可能會顯示一個正在Loading裝載進度,以得到良好的體驗。html
<!DOCTYPE html> <html lang="en"> <head> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script> </head> <body> <form name="form-payment" id="form-payment"> ... </form> <script type="text/javascript"> $('#form-payment').submit(function (e) { e.preventDefault(); $.ajax({ type: 'POST', dataType : "json", contentType: "application/json; charset=utf-8", url: "#", data: "{}", beforeSend: function(){ $('#button-submit').attr('disabled', 'disable'); }, complete: function(){ $('#button-submit').removeAttr('disabled'); }, success: function (data) { // do your success action }, error: function () { // do your error handler } }); }); </script> </body>
在beforeSend 和complete段,我添加「 disable」屬性做爲開關, (jquery中有專門語句防止二次提交)java
重點來了:jquery
這種技術實際上更復雜,更難實現,可是因爲一個好的框架(如Spring Boot)使這更容易。在咱們開始代碼實現以前,讓咱們先討論一下這個機制;web
咱們來開始代碼。這裏是個人JavaScript中的示例代碼,用於發出新的requestId。ajax
$(document).ready(function () { var requestId = new Date().getTime(); // <--- issue new requestId every time page laoded $('#form-payment').submit(function (e) { e.preventDefault(); $.ajax({ type: 'POST', dataType : "json", contentType: "application/json; charset=utf-8", headers: { "requestId" : requestId }, // <--- add requestId in header url: "#", data: "{}", beforeSend: function(){ $('#button-submit').attr('disabled', 'disable'); }, complete: function(){ $('#button-submit').removeAttr('disabled'); }, success: function (data) { }, error: function () { } }); }); });
這裏是個人Spring Boot項目中的示例代碼,我建立了一個Interceptor來處理requestId:spring
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.ArrayList; import java.util.List; @Configuration public class Interceptor implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new ViolationInterceptor()).addPathPatterns("/**"); } public class ViolationInterceptor extends HandlerInterceptorAdapter { private List<String> requestIds = new ArrayList<>(); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String requestId = request.getHeader("requestId"); if (requestIds.contains(requestId)) throw new IllegalArgumentException("Violation Request; Reason requestId already registered"); requestIds.add(requestId); return super.preHandle(request, response, handler); } } }
Exception處理:數據庫
import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; @ControllerAdvice public class ExceptionAdvisor { @ExceptionHandler(IllegalArgumentException.class) ResponseEntity illegalArgumentExceptionHandler(IllegalArgumentException e){ return ResponseEntity.ok(e.getMessage()); } }
在此示例中,我使用應用程序內存來存儲requestId。對於認真的開發,我建議使用內存數據庫,例如Redis。json
實際上,咱們能夠在識別requestId時修改如何發佈新令牌和邏輯。由於這個過程很是簡單,咱們須要一些東西(requestId)來識別已經請求過的東西。後端
既然看到這裏了,以爲筆者寫的還不錯的就點個贊,加個關注唄!點關注,不迷路,持續更新!!!