zoukankan      html  css  js  c++  java
  • 防重提交-开发思路

    情况:在我们插入数据以后,只要刷新页面,就会重新插入这条数据。

    原因:在我们提交数据后,浏览器会保留上一次请求的数据!!在刷新页面的时候,会将上一次请求重新发送一次,导致了重提交问题的出现。

    问题:如果解决重提交的问题呢?

    答:解决思路是,在重提交的时候,让请求不要重新发送上一次的请求。那么我们需要实现防重提交的机制。实现防重提交的机制,是使用Token(令牌机制)实现的。

    所以要解决这个问题,首先理解token机制的实现!!  

    实现一个拦截器。拦截多个请求。

    第一步:新建一个拦截器

    import java.util.ArrayList;
    import java.util.List;
    import java.util.UUID;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    import org.chu.annotation.TokenForm;
    import org.springframework.web.method.HandlerMethod;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    /**
     * 防重提交
     * @author ranger
     *
     */
    public class TokenInterceptor implements HandlerInterceptor {
    
        @SuppressWarnings("unchecked")
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            //第一步:如果是一个增加的请求,我们就创建一个Token
            //问题:如何标志请求的方法是一个增加的方法呢?通过注解来标识
            //HandlerMethod对象可以获得请求准备要调用的方法的方法信息
            List<String> tokenPool=null;
            HandlerMethod hm=(HandlerMethod) handler;
            TokenForm tokenForm = hm.getMethodAnnotation(TokenForm.class);
            if (tokenForm!=null) {
                HttpSession session = request.getSession();
                //问题:如果多个功能使用的SessionToken是同一个。会出现相互覆盖的情况
                //解决方案,使用一个集合来存储sessionToken。将Token分为当前Token (用于返回到页面),Token池
                if (session.getAttribute("tokenPool")==null) {
                    tokenPool=new ArrayList<>();
                }else {
                    tokenPool=(List<String>) session.getAttribute("tokenPool");
                }
                //只要,进入或者提交都要出境一个新的Token放在Session里面
                String sessionToken = UUID.randomUUID().toString();
                //将创建的Token放在会话的tokenPool里面
                tokenPool.add(sessionToken);
                //将创建的Token放在会话方放在一个字段里面用于返回到页面
                session.setAttribute("sessionToken", sessionToken);
                session.setAttribute("tokenPool", tokenPool);
                
                //remove为true,表示是一个提交增加的请求
                if (tokenForm.remove()) {
                    //判断请求表单的token和会话里面的Token是否相同
                    String formToken = request.getParameter("formToken");
                    List<String> resultTokenPool = (List<String>) session.getAttribute("tokenPool");
                    boolean flag=false;
                    for (String token : resultTokenPool) {
                        if (token.equals(formToken)) {
                            //如果发现token池有对应的Token就移除
                            resultTokenPool.remove(token);
                            flag=true;
                            break;
                        }
                    }
                    //如果表单的Token在Token池里面没有。就跳转到指定的页面
                    if (flag==false) {
        
                        response.sendRedirect(request.getParameter("token.invoke"));
                        return false;
                    }
                }
            }
            
            
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                ModelAndView modelAndView) throws Exception {
            
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
                throws Exception {
            
        }
    
    }

    问题:如何标志请求的方法是一个增加的方法呢?通过注解来标识

    import java.lang.annotation.Documented;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * 用于防重提标志需要防重提交的方法
     * @author ranger
     *
     */
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface TokenForm {
        //如果create为true,表示是一个跳转到增加页面的请求
        boolean create()  default false;
        //如果是remove为true,表示是一个增加提交的请求
        boolean remove()  default false;
    
    }

    第二步:在controller在相应的方法加上注解

    第三步:在springmvc配置文件或者配置类设置拦截器ok

  • 相关阅读:
    机器学习推荐系统架构图
    mysql 的读写分离 以及mycat 实现集群管理
    逻辑回归 评价推荐质量 计算AUC
    jquery编写开关实现div的显示与隐藏
    php页面post方法实现ajax,入门实例教程
    php页面get方法实现ajax,入门实例教程
    JavaScript for...in 循环 JavaScript for...in 语句循环遍历对象的属性。
    删除已有的 HTML 元素
    创建新的 HTML 元素
    js常用事件及其用法
  • 原文地址:https://www.cnblogs.com/vieta/p/11156710.html
Copyright © 2011-2022 走看看