zoukankan      html  css  js  c++  java
  • SpringMVC:拦截器拦截时机和原理

    测试

    先自定义一个拦截器

    public class MyInterceptor implements HandlerInterceptor {
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("preHandle");
            return true;
        }
    
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            System.out.println("postHandle");
        }
    
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            System.out.println("afterCompletion");
        }
    }
    

    注册该拦截器

    @Configuration
    public class WebConfig implements WebMvcConfigurer {
    
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new MyInterceptor()).addPathPatterns("/*");
        }
    }
    

    测试,访问接口:

    image-20210407143348235

    原理

    对DispatcherServlet的方法doDispatch打上断点

    image-20210407143648829

    getHandler不仅找到了当前请求的处理器,并且找到了对应的拦截器。

    断点继续往下走,在执行目标方法之前,调用了applyPreHandle方法,所以猜测这里就会调用拦截器preHandle方法,并且该方法如果返回false,就会return(被拦截)

    image-20210407144255910

    进入applyPreHandle方法,这里先顺序执行所有的拦截器的preHandle方法,只要有一个返回了false,就会调用triggerAfterCompletion方法,然后跳出循环

    image-20210407144807453

    triggerAfterCompletion方法:注意,这里从当前拦截器开始倒序执行前面以前已经执行过的拦截器的afterCompletion方法

    image-20210407145246760

    目标方法执行后,调用了applyPostHandle方法

    image-20210407145639651

    applyPostHandle源代码:这里会倒序执行所有的拦截器的postHandle方法

    image-20210407145735418

    继续往下看:

    image-20210407150203832

    processDispatchResult方法内部会倒序调用所有拦截器afterCompletion方法,意味着如果全部流程执行完了,中间没有任何异常,会调用afterCompletion方法

    如果中间过程中出现了异常,会调用triggerAfterCompletion方法,该方法仍然会倒序执行所有拦截器的afterCompletion方法。

    图示:

    image-20210407150725693

    总结

    1、根据当前请求,找到HandlerExecutionChain【可以处理请求的handler以及handler的所有 拦截器】

    2、先来顺序执行 所有拦截器的 preHandle方法

    • 1、如果当前拦截器prehandler返回为true。则执行下一个拦截器的preHandle
    • 2、如果当前拦截器返回为false。直接 倒序执行所有已经执行了的拦截器的 afterCompletion;

    3、如果任何一个拦截器返回false。直接跳出不执行目标方法

    4、所有拦截器都返回True。执行目标方法

    5、倒序执行所有拦截器的postHandle方法。

    6、前面的步骤有任何异常都会直接倒序触发 afterCompletion

    7、页面成功渲染完成以后,也会倒序触发 afterCompletion

  • 相关阅读:
    Java:类与继承(隐藏和覆盖的问题)
    Java中的static关键字解析
    面向对象(Java中普通代码块,构造代码块,静态代码块区别及代码示例)
    面向对象要点(this关键字)
    急须知道postman RSA加密的方式
    RSA加密原理
    postman获取变量
    Mysql通过cmd访问
    一个简单的postman实例
    sum(coalesce(adjust_value,prediction_value))
  • 原文地址:https://www.cnblogs.com/wwjj4811/p/14627812.html
Copyright © 2011-2022 走看看