为防止重复提交,一般分为前端和后端。
1. 前端一般是通过JS,在用户点击提交按钮后,失效,或者增加div提示提交中,来遮挡。
$(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 () {
}
});
});
});
2. 第二种是通过拦截器,通过页面的TOKEN值,来注册判断,短时间是否存在重复。
3.编写spring框架的验证拦截器。此处springBoots,也可编写spring拦截器,不过sping拦截器使用的是session,key值。
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);
}
}
}
编写controller advice
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());
}
}
以上方法真的是框架级的解决方案,structs1,就自带了token id,来验证表单是否提交,需要前台配合strucs1的 form 标签使用。