【spring mvc】Spring MVC拦截器+注解方式实现防止表单重复提交

本文介绍了一种基于Session和自定义注解的防重复提交机制,通过在新建页面中保存token并验证来避免多次提交。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

方法很多,先转载下,后面一个个实验,获得最优方案


原理:在新建页面中Session保存token随机码,当保存时验证,通过后删除,当再次点击保存时由于服务器端的Session中已经不存在了,所有无法验证通过。

1.新建注解:

[java]  view plain  copy
  1. /** 
  2.  * <p> 
  3.  * 防止重复提交注解,用于方法上<br/> 
  4.  * 在新建页面方法上,设置needSaveToken()为true,此时拦截器会在Session中保存一个token, 
  5.  * 同时需要在新建的页面中添加 
  6.  * <input type="hidden" name="token" value="${token}"> 
  7.  * <br/> 
  8.  * 保存方法需要验证重复提交的,设置needRemoveToken为true 
  9.  * 此时会在拦截器中验证是否重复提交 
  10.  * </p> 
  11.  * @author: chuanli 
  12.  * @date: 2013-6-27上午11:14:02 
  13.  * 
  14.  */  
  15. @Target(ElementType.METHOD)  
  16. @Retention(RetentionPolicy.RUNTIME)  
  17. public @interface AvoidDuplicateSubmission {  
  18.     boolean needSaveToken() default false;  
  19.     boolean needRemoveToken() default false;  
  20. }  

2. 新建拦截器

[java]  view plain  copy
  1. /** 
  2.  * <p> 
  3.  * 防止重复提交过滤器 
  4.  * </p> 
  5.  * 
  6.  * @author: chuanli 
  7.  * @date: 2013-6-27上午11:19:05 
  8.  */  
  9. public class AvoidDuplicateSubmissionInterceptor extends HandlerInterceptorAdapter {  
  10.     private static final Logger LOG = Logger.getLogger(AvoidDuplicateSubmissionInterceptor.class);  
  11.   
  12.     @Override  
  13.     public boolean preHandle(HttpServletRequest request,  
  14.             HttpServletResponse response, Object handler) throws Exception {  
  15.   
  16.         User user = UserUtil.getUser();  
  17.         if (user != null) {  
  18.             HandlerMethod handlerMethod = (HandlerMethod) handler;  
  19.             Method method = handlerMethod.getMethod();  
  20.   
  21.             AvoidDuplicateSubmission annotation = method.getAnnotation(AvoidDuplicateSubmission.class);  
  22.             if (annotation != null) {  
  23.                 boolean needSaveSession = annotation.needSaveToken();  
  24.                 if (needSaveSession) {  
  25.                     request.getSession(false).setAttribute("token", TokenProcessor.getInstance().generateToken());  
  26.                 }  
  27.   
  28.                 boolean needRemoveSession = annotation.needRemoveToken();  
  29.                 if (needRemoveSession) {  
  30.                     if (isRepeatSubmit(request)) {  
  31.                         LOG.warn("please don't repeat submit,[user:" + user.getUsername() + ",url:"  
  32.                                 + request.getServletPath() + "]");  
  33.                         return false;  
  34.                     }  
  35.                     request.getSession(false).removeAttribute("token");  
  36.                 }  
  37.             }  
  38.         }  
  39.         return true;  
  40.     }  
  41.   
  42.     private boolean isRepeatSubmit(HttpServletRequest request) {  
  43.         String serverToken = (String) request.getSession(false).getAttribute("token");  
  44.         if (serverToken == null) {  
  45.             return true;  
  46.         }  
  47.         String clinetToken = request.getParameter("token");  
  48.         if (clinetToken == null) {  
  49.             return true;  
  50.         }  
  51.         if (!serverToken.equals(clinetToken)) {  
  52.             return true;  
  53.         }  
  54.         return false;  
  55.     }  
  56.   
  57. }  

3. 在Spring中配置

[html]  view plain  copy
  1. <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">  
  2.    <property name="interceptors">  
  3.       <list>  
  4.           <bean class="com.sohu.tv.crm.aop.UserLogInterceptor"/>  
  5.           <bean class="com.sohu.tv.crm.aop.AvoidDuplicateSubmissionInterceptor"/>  
  6.       </list>  
  7.    </property>  
  8.   
  9. </bean>  

4. 在相关方法中加入注解:

[java]  view plain  copy
  1. @RequestMapping("/save")  
  2.  @AvoidDuplicateSubmission(needRemoveToken = true)  
  3.     public synchronized ModelAndView save(ExecutionUnit unit, HttpServletRequest request, HttpServletResponse response)  
  4.             throws Exception {  
  5.   
  6. @RequestMapping("/edit")  
  7.     @AvoidDuplicateSubmission(needSaveToken = true)  
  8.     public ModelAndView edit(Integer id, HttpServletRequest request) throws Exception {  

5.在新建页面中加入
                <input type="hidden" name="token" value="${token}">

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值