zoukankan      html  css  js  c++  java
  • SpringMVC拦截器使用流程和源码分析

    1、SpringMVC拦截器的使用流程

      1)、在spring-servlet.xml中配置拦截器信息。

    <!--    调试拦截器-->
        <mvc:interceptors>
            <!-- 配置某个拦截器,默认拦截所有请求 -->
    <!--        <bean class="com.lxy.controller.FilterController"></bean>-->
    
            <!-- 配置某个拦截器更详细的信息 -->
            <mvc:interceptor>
                <!--只拦截test01请求-->
                <mvc:mapping path="/test01"/>
                <bean class="com.lxy.controller.FilterController">
    
                </bean>
            </mvc:interceptor>
        </mvc:interceptors>

      2)、写自己的拦截器并实现 HandlerInterceptor接口

    public class MyFilter 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");
        }
    }

        重点是实现 preHandle、postHandle、afterCompletion三个方法

    2、SpringMVC拦截器运行流程

      正常流程:

         拦截器的preHandle--->目标方法---->拦截器的postHandle---->页面----->拦截器的afterCompletion

      其他流程:

        只要preHandle不放行,就没有下面的流程。 只要放行了,afterCompletion都会执行

    3、SpringMVC拦截器源码分析

      SpringMVC的核心方法doDispatch() 源码如下  ---------------之前的随笔也分析过 ------------------  

    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
            HttpServletRequest processedRequest = request;
            HandlerExecutionChain mappedHandler = null;
            boolean multipartRequestParsed = false;
    
            WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    
            try {
                ModelAndView mv = null;
                Exception dispatchException = null;
    
                try {
                    processedRequest = checkMultipart(request);
                    multipartRequestParsed = (processedRequest != request);
    
                    // Determine handler for the current request.
                    mappedHandler = getHandler(processedRequest);
                    if (mappedHandler == null) {
                        noHandlerFound(processedRequest, response);
                        return;
                    }
    
                    // Determine handler adapter for the current request.
                    HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
    
                    // Process last-modified header, if supported by the handler.
                    String method = request.getMethod();
                    boolean isGet = "GET".equals(method);
                    if (isGet || "HEAD".equals(method)) {
                        long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
                        if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
                            return;
                        }
                    }
              //  在目标方法执行之前,会先执行preHandle方法 如何返回false就直接返回了  下面统统不执行
                    if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                        return;
                    }
    
                    // 执行目标方法
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }
    
                    applyDefaultViewName(processedRequest, mv);
              // 在执行完目标方法之后,会执行拦截器的postHandler方法 mappedHandler.applyPostHandle(processedRequest, response, mv); }
    catch (Exception ex) { dispatchException = ex; } catch (Throwable err) { // As of 4.3, we're processing Errors thrown from handler methods as well, // making them available for @ExceptionHandler methods and other scenarios. dispatchException = new NestedServletException("Handler dispatch failed", err); }
           // 渲染页面,并在该方法中执行afterCompletion方法 processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException); }
    catch (Exception ex) {
            // 即使上面执行的方法抛出了异常,afterCompletion的方法依然会被执行 triggerAfterCompletion(processedRequest, response, mappedHandler, ex); }
    catch (Throwable err) { triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", err)); } finally { if (asyncManager.isConcurrentHandlingStarted()) { // Instead of postHandle and afterCompletion if (mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else { // Clean up any resources used by a multipart request. if (multipartRequestParsed) { cleanupMultipart(processedRequest); } } } }

        1)、preHandle方法是如何执行的(applyPreHandle方法)

    boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
         // 得到所有的拦截器 HandlerInterceptor[] interceptors
    = getInterceptors(); if (!ObjectUtils.isEmpty(interceptors)) {
           // 循环正序遍历所有的拦截器
    for (int i = 0; i < interceptors.length; i++) { HandlerInterceptor interceptor = interceptors[i];
              // 执行拦截器方法,并返回true/false 来当前方法,preHandler是否放行了
    if (!interceptor.preHandle(request, response, this.handler)) {
                // 执行到这,说明preHandler返回的是false,就是不放行,那么就执行完下面方法(afterCompletion方法的执行方法),直接返回,不纪录拦截器索引
             // 由于没有纪录当前拦截器索引,所以即使执行了下面方法,当前拦截器的afterCompletion也不会被执行
    triggerAfterCompletion(request, response,
    null); return false; }
              // 纪录拦截器索引最远达到的位置,为之后执行afterCompletion方法做准备
           // 说明:如果索引为1的拦截器的preHandle方法返回的是false,即使索引为2的拦截器的preHandle方法返回的是true,索引为2的拦截器的postHandle等后面所有方法统统不执行
    this.interceptorIndex = i; } } return true;

        2)、postHandle方法是如何执行的(applyPostHandle) 

    void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
                throws Exception {
    
            HandlerInterceptor[] interceptors = getInterceptors();
            if (!ObjectUtils.isEmpty(interceptors)) {
           // 逆序遍历所有的拦截器,并执行postHandler方法
    for (int i = interceptors.length - 1; i >= 0; i--) { HandlerInterceptor interceptor = interceptors[i]; interceptor.postHandle(request, response, this.handler, mv); } } }

        3)、afterCompletion方法是如何执行的 

            先来到 processDispatchResult方法

    private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
                @Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
                @Nullable Exception exception) throws Exception {
    
            boolean errorView = false;
         // 先进行页面渲染
            if (exception != null) {
                if (exception instanceof ModelAndViewDefiningException) {
                    logger.debug("ModelAndViewDefiningException encountered", exception);
                    mv = ((ModelAndViewDefiningException) exception).getModelAndView();
                }
                else {
                    Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
                    mv = processHandlerException(request, response, handler, exception);
                    errorView = (mv != null);
                }
            }
    
            // Did the handler return a view to render?
            if (mv != null && !mv.wasCleared()) {
                render(mv, request, response);
                if (errorView) {
                    WebUtils.clearErrorRequestAttributes(request);
                }
            }
            else {
                if (logger.isTraceEnabled()) {
                    logger.trace("No view rendering, null ModelAndView returned.");
                }
            }
    
            if (WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
                // Concurrent handling started during a forward
                return;
            }
         // 页面渲染完成后,执行afterCompletion方法
            if (mappedHandler != null) {
                mappedHandler.triggerAfterCompletion(request, response, null);
            }
        }

            页面渲染完成之后,执行 triggerAfterCompletion 方法

    void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex)
                throws Exception {
    
            HandlerInterceptor[] interceptors = getInterceptors();
            if (!ObjectUtils.isEmpty(interceptors)) {
           // 遍历所有之前preHandle方法放行的拦截器,interceptorIndex就是之前在执行preHandle方法时候,如果返回的是true就纪录一下
    for (int i = this.interceptorIndex; i >= 0; i--) { HandlerInterceptor interceptor = interceptors[i]; try { interceptor.afterCompletion(request, response, this.handler, ex); } catch (Throwable ex2) { logger.error("HandlerInterceptor.afterCompletion threw exception", ex2); } } } }
  • 相关阅读:
    2017 多校联合训练 8 题解
    2017 多校联合训练 7 题解
    2017 多校联合训练 6 题解
    2017 多校联合训练 5 题解
    2017 多校联合训练 4 题解
    windows 安装python
    pygame 使用
    python 发布
    面向对象的思维方法
    python 基础
  • 原文地址:https://www.cnblogs.com/lxy-java/p/12936334.html
Copyright © 2011-2022 走看看