zoukankan      html  css  js  c++  java
  • 拦截器springmvc防止表单重复提交【2】

    【参考博客:http://my.oschina.net/mushui/blog/143397】
    原理:在新建页面中Session保存token随机码,当保存时验证,通过后删除,当再次点击保存时由于服务器端的Session中已经不存在了,所有无法验证通过。
     

    1.新建注解:

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

    2. 新建拦截器

    /**
     * <p>
     * 防止重复提交过滤器
     * </p>
     *
     * @author: chuanli
     * @date: 2013-6-27上午11:19:05
     */
    public class AvoidDuplicateSubmissionInterceptor extends HandlerInterceptorAdapter {
        private static final Logger LOG = Logger.getLogger(AvoidDuplicateSubmissionInterceptor.class);
    
        @Override
        public boolean preHandle(HttpServletRequest request,
                HttpServletResponse response, Object handler) throws Exception {
    
            User user = UserUtil.getUser();
            if (user != null) {
                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(false).setAttribute("token", TokenProcessor.getInstance().generateToken());
                    }
    
                    boolean needRemoveSession = annotation.needRemoveToken();
                    if (needRemoveSession) {
                        if (isRepeatSubmit(request)) {
                            LOG.warn("please don't repeat submit,[user:" + user.getUsername() + ",url:"
                                    + request.getServletPath() + "]");
                            return false;
                        }
                        request.getSession(false).removeAttribute("token");
                    }
                }
            }
            return true;
        }
    
        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. 在Spring中配置

    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
       <property name="interceptors">
          <list>
              <bean class="com.sohu.tv.crm.aop.UserLogInterceptor"/>
              <bean class="com.sohu.tv.crm.aop.AvoidDuplicateSubmissionInterceptor"/>
          </list>
       </property>
    
    </bean>
     

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

    @RequestMapping("/save")
     @AvoidDuplicateSubmission(needRemoveToken = true)
        public synchronized ModelAndView save(ExecutionUnit unit, HttpServletRequest request, HttpServletResponse response)
                throws Exception {
    
    @RequestMapping("/edit")
        @AvoidDuplicateSubmission(needSaveToken = true)
        public ModelAndView edit(Integer id, HttpServletRequest request) throws Exception {
    5.在新建页面中加入
                    <input type="hidden" name="token" value="${token}">
  • 相关阅读:
    数据库基础
    Junit单元测试、反射与注解
    Stream流
    Java IO所用类
    字符集
    Lambda表达式
    【jdk1.8源码分析】LinkedHashMap
    线性表
    【jdk1.8源码分析】ArrayList
    java学习血泪史
  • 原文地址:https://www.cnblogs.com/dixinyunpan/p/5830758.html
Copyright © 2011-2022 走看看