场景: 用户手速单身一百年(活该单身狗 虽然我也是哈哈) 一秒连续点击提交按钮 导致插入多条数据 。网上找的资料 自己记录一下,勿喷!
一、java代码:
1.新建注解
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by 罗鸿强 on 2016/9/10. */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface AvoidDuplicateSubmission { boolean needSaveToken() default false; boolean needRemoveToken() default false; }
2.新建拦截器
import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.lang.reflect.Method; import java.util.UUID; /** * Created by LOL 征服之海 7333 */ public class AvoidDuplicateSubmissionInterceptor extends HandlerInterceptorAdapter{ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler)throws Exception{ /* private static final Logger LOG = Logger.getLogger(AvoidDuplicateSubmission.class);*/ if (handler instanceof HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) handler; Method method = handlerMethod.getMethod(); AvoidDuplicateSubmission annotation = method.getAnnotation(AvoidDuplicateSubmission.class); if (annotation != null) { boolean needSaveSession = annotation.needSaveToken(); if (needSaveSession) { request.getSession(true).setAttribute("token", UUID.randomUUID().toString()); } boolean needRemoveSession = annotation.needRemoveToken(); if (needRemoveSession) { if (isRepeatSubmit(request)) { /*LOG.warn("please don't repeat submit,url:"+ request.getServletPath());*/ return false; } request.getSession(true).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 clinetToken = request.getParameter("token"); if (clinetToken == null) { return true; } if (!serverToken.equals(clinetToken)) { return true; } return false; } }
3.sevlet.xml中配置拦截器
<mvc:interceptors> <!-- 配置Token拦截器,防止用户重复提交数据 --> <mvc:interceptor> <mvc:mapping path="/member/*"/><!--因为跳转数据的时候传TOKEN,提交的时候获取TOKEN 所以我把路径设为/member/*--> <bean class="com.tanbao.common.AvoidDuplicateSubmissionInterceptor"/><!--class文件路径改成你自己写得拦截器路径!! --> </mvc:interceptor> </mvc:interceptors>
4.跳转表单页面的时候加上你刚写好的自定义注解 属性为(needSaveToken=true)
@RequestMapping(value = "/authlist", method = RequestMethod.GET) @AvoidDuplicateSubmission(needSaveToken =true) public String authList() {
5.提交的方法也加注解 属性(needRemoveToken=true)
@RequestMapping(value = "/updateUserAuth", method = RequestMethod.POST) @AvoidDuplicateSubmission(needRemoveToken = true) public String updateUserAuth(HttpServletRequest request) {
6.表单页面上别忘了加
<input type="hidden" name="token" value="${token}">
就这么简单。我之前各种JS 防止提交表单未成功。。。。