zoukankan      html  css  js  c++  java
  • SpringMVC 拦截器

    拦截器接口-HandlerInterceptor

    自定义的拦截器,需要继承HandlerInterceptor接口,并且实现HandlerInterceptor中提供的三个方法:

    1. preHandle 方法会在请求处理前被调用。这个方法返回boolean值,如果返回true则继续往下执行,如果返回false则中断。

    2. postHandle 方法会在请求处理后,继续调用。

    3. afterCompletion 方法会在视图渲染之后调用。

    代码:

    package org.springframework.web.servlet;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.springframework.web.servlet.ModelAndView;
    
    public interface HandlerInterceptor {
        boolean preHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3) throws Exception;
    
        void postHandle(HttpServletRequest var1, HttpServletResponse var2, Object var3, ModelAndView var4) throws Exception;
    
        void afterCompletion(HttpServletRequest var1, HttpServletResponse var2, Object var3, Exception var4) throws Exception;
    }

    在什么地方调用该接口方法呢

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by Fernflower decompiler)
    //
    
    package org.springframework.web.servlet;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.springframework.util.CollectionUtils;
    import org.springframework.util.ObjectUtils;
    import org.springframework.web.servlet.AsyncHandlerInterceptor;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    public class HandlerExecutionChain {
        private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);
        private final Object handler;
        private HandlerInterceptor[] interceptors;
        private List<HandlerInterceptor> interceptorList;
        private int interceptorIndex;
    
        public HandlerExecutionChain(Object handler) {
            this(handler, (HandlerInterceptor[])null);
        }
    
        public HandlerExecutionChain(Object handler, HandlerInterceptor... interceptors) {
            this.interceptorIndex = -1;
            if(handler instanceof HandlerExecutionChain) {
                HandlerExecutionChain originalChain = (HandlerExecutionChain)handler;
                this.handler = originalChain.getHandler();
                this.interceptorList = new ArrayList();
                CollectionUtils.mergeArrayIntoCollection(originalChain.getInterceptors(), this.interceptorList);
                CollectionUtils.mergeArrayIntoCollection(interceptors, this.interceptorList);
            } else {
                this.handler = handler;
                this.interceptors = interceptors;
            }
    
        }
    
        public Object getHandler() {
            return this.handler;
        }
    
        public void addInterceptor(HandlerInterceptor interceptor) {
            this.initInterceptorList().add(interceptor);
        }
    
        public void addInterceptors(HandlerInterceptor... interceptors) {
            if(!ObjectUtils.isEmpty(interceptors)) {
                this.initInterceptorList().addAll(Arrays.asList(interceptors));
            }
    
        }
    
        private List<HandlerInterceptor> initInterceptorList() {
            if(this.interceptorList == null) {
                this.interceptorList = new ArrayList();
                if(this.interceptors != null) {
                    this.interceptorList.addAll(Arrays.asList(this.interceptors));
                }
            }
    
            this.interceptors = null;
            return this.interceptorList;
        }
    
        public HandlerInterceptor[] getInterceptors() {
            if(this.interceptors == null && this.interceptorList != null) {
                this.interceptors = (HandlerInterceptor[])this.interceptorList.toArray(new HandlerInterceptor[this.interceptorList.size()]);
            }
    
            return this.interceptors;
        }
        //调用preHandle
        boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
            HandlerInterceptor[] interceptors = this.getInterceptors();
            if(!ObjectUtils.isEmpty(interceptors)) {
                for(int i = 0; i < interceptors.length; this.interceptorIndex = i++) {
                    HandlerInterceptor interceptor = interceptors[i];
                    if(!interceptor.preHandle(request, response, this.handler)) {
                        this.triggerAfterCompletion(request, response, (Exception)null);
                        return false;
                    }
                }
            }
    
            return true;
        }
       //调用postHandle
        void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
            HandlerInterceptor[] interceptors = this.getInterceptors();
            if(!ObjectUtils.isEmpty(interceptors)) {
                for(int i = interceptors.length - 1; i >= 0; --i) {
                    HandlerInterceptor interceptor = interceptors[i];
                    interceptor.postHandle(request, response, this.handler, mv);
                }
            }
    
        }
       //调用afterCompletion
        void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex) throws Exception {
            HandlerInterceptor[] interceptors = this.getInterceptors();
            if(!ObjectUtils.isEmpty(interceptors)) {
                for(int i = this.interceptorIndex; i >= 0; --i) {
                    HandlerInterceptor interceptor = interceptors[i];
    
                    try {
                        interceptor.afterCompletion(request, response, this.handler, ex);
                    } catch (Throwable var8) {
                        logger.error("HandlerInterceptor.afterCompletion threw exception", var8);
                    }
                }
            }
    
        }
    
        void applyAfterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response) {
            HandlerInterceptor[] interceptors = this.getInterceptors();
            if(!ObjectUtils.isEmpty(interceptors)) {
                for(int i = interceptors.length - 1; i >= 0; --i) {
                    if(interceptors[i] instanceof AsyncHandlerInterceptor) {
                        try {
                            AsyncHandlerInterceptor ex = (AsyncHandlerInterceptor)interceptors[i];
                            ex.afterConcurrentHandlingStarted(request, response, this.handler);
                        } catch (Throwable var6) {
                            logger.error("Interceptor [" + interceptors[i] + "] failed in afterConcurrentHandlingStarted", var6);
                        }
                    }
                }
            }
    
        }
    
        public String toString() {
            if(this.handler == null) {
                return "HandlerExecutionChain with no handler";
            } else {
                StringBuilder sb = new StringBuilder();
                sb.append("HandlerExecutionChain with handler [").append(this.handler).append("]");
                if(!CollectionUtils.isEmpty(this.interceptorList)) {
                    sb.append(" and ").append(this.interceptorList.size()).append(" interceptor");
                    if(this.interceptorList.size() > 1) {
                        sb.append("s");
                    }
                }
    
                return sb.toString();
            }
        }
    }

     那么在什么地方调用HandlerExecutionChain中的applyPreHandle,applyPostHandle,triggerAfterCompletion方法呢

    嗯,在大名鼎鼎的DispatcherServlet.class中,这个类就是SpringMVC的核心。

    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 err = null;
                Exception dispatchException = null;
    
                try {
                    processedRequest = this.checkMultipart(request);
                    multipartRequestParsed = processedRequest != request;
                    mappedHandler = this.getHandler(processedRequest);
                    if(mappedHandler == null || mappedHandler.getHandler() == null) {
                        this.noHandlerFound(processedRequest, response);
                        return;
                    }
    
                    HandlerAdapter ex = this.getHandlerAdapter(mappedHandler.getHandler());
                    String method = request.getMethod();
                    boolean isGet = "GET".equals(method);
                    if(isGet || "HEAD".equals(method)) {
                        long lastModified = ex.getLastModified(request, mappedHandler.getHandler());
                        if(this.logger.isDebugEnabled()) {
                            this.logger.debug("Last-Modified value for [" + getRequestUri(request) + "] is: " + lastModified);
                        }
    
                        if((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
                            return;
                        }
                    }
                    //调用applyPreHandle
                    if(!mappedHandler.applyPreHandle(processedRequest, response)) {
                        return;
                    }
    
                    err = ex.handle(processedRequest, response, mappedHandler.getHandler());
                    if(asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }
    
                    this.applyDefaultViewName(processedRequest, err);
    //调用applyPostHandle mappedHandler.applyPostHandle(processedRequest, response, err); }
    catch (Exception var19) { dispatchException = var19; } this.processDispatchResult(processedRequest, response, mappedHandler, err, dispatchException); } catch (Exception var20) {
    this.triggerAfterCompletion(processedRequest, response, mappedHandler, var20); } catch (Error var21) { this.triggerAfterCompletionWithError(processedRequest, response, mappedHandler, var21); } finally { if(asyncManager.isConcurrentHandlingStarted()) { if(mappedHandler != null) { mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response); } } else if(multipartRequestParsed) { this.cleanupMultipart(processedRequest); } } }

    这边还有一个网上牛人的注释版

    protected void doDispatch(HttpServletRequest request,
                                  HttpServletResponse response) throws Exception {
    
            // processedRequest是经过checkMultipart方法处理过的request请求
            HttpServletRequest processedRequest = request;
            /**
             * Handler execution chain, consisting of handler object and any handler
             * interceptors. Returned by HandlerMapping's HandlerMapping.getHandler
             * method. 看看HandlerExecutionChain类的属性就很清楚了:
             *
             public class HandlerExecutionChain {
    
             private final Object handler; //这个就是和该请求对应的handler处理方法
    
             //里面记录了所有的(any handler interceptors)和该请求相关的拦截器
             private HandlerInterceptor[] interceptors;
    
             private List<HandlerInterceptor> interceptorList; 
    
             private int interceptorIndex = -1; 
    
             //... 
             }
             *
             */
            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.Return a handler
                    // and any interceptors for this request.
                    /*
                     * 得到的mappedHandler包含一个请求的handler处理方法以及与该请求相关的所有拦截器
                     * 
                     * DispatcherServlet.getHandler方法会在底层调用HandlerMapping.getHandler方法
                     * ,这个方法中会遍 历DispatcherServlet中的private List<HandlerMapping>
                     * handlerMappings链表,找到能够处理当前 request请求的第一个HandlerMapping实例并返回:
                     * 
                      protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
                          for (HandlerMapping hm : this.handlerMappings) {
                                  HandlerExecutionChain handler = hm.getHandler(request);
                                  if (handler != null) {
                                         return handler;
                                  }
                          }
                          return null;
                      }
                     *
                     */
                    mappedHandler = getHandler(processedRequest);
                    // 如果没有找到和该请求相对应的mappedHandler,那么就会直接返回,并应答noHandlerFound异常
                    if (mappedHandler == null || mappedHandler.getHandler() == null) {
                        noHandlerFound(processedRequest, response);
                        return;
                    }
    
                    // Determine handler adapter for the current request.
                    /*
                     * HandlerAdapter: 它是一个接口public interface HandlerAdapter
                     * 看看源码上的说明:The DispatcherServlet accesses all installed
                     * handlers through this interface, meaning that it does not
                     * contain code specific to any handler type.
                     * 
                     * 从后面的源码看出,在使用@RequestMapping注解标注handler方法的时候,获取到的是HandlerAdapter的
                     * RequestMappingHandlerAdapter实现类的一个对象。
                     * 
                     * 可以看看DispatcherServlet.getHandlerAdapter方法的定义,这个对理解上回很有帮助,我们会发现
                     * ,getHandlerAdapter 方法和上面提到的getHandler方法一样都是寻找第一个可用的作为返回结果:
                     *
                     * 
                      protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
                         //this.handlerAdapters的定义是 private List<HandlerAdapter> handlerAdapters
                             for (HandlerAdapter ha : this.handlerAdapters) { 
                                  if (ha.supports(handler)) {
                                       return ha;
                                  }
                             }
                             throw new ServletException("No adapter for handler [" + handler +
                                     "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
                      }
                     * 
                     */
                    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 (logger.isDebugEnabled()) {
                            logger.debug("Last-Modified value for ["
                                    + getRequestUri(request) + "] is: "
                                    + lastModified);
                        }
                        if (new ServletWebRequest(request, response)
                                .checkNotModified(lastModified) && isGet) {
                            return;
                        }
                    }
    
                    // Apply preHandle methods of registered interceptors.
                    /*
                     * 会调用所有注册拦截器的preHandle方法,如果preHandle方法的返回结果为true,则会继续执行下面的程序,
                     * 否则会直接返回。
                     * 
                     * 分析一下HandlerExecutionChain.applyPreHandle方法的源码 :
                      boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
                             //从上面的HandlerExecutionChain定义处可以看见有个interceptors,还有一个interceptorList。不知道有什么区别??!
                             HandlerInterceptor[] interceptors = getInterceptors();
                             //如果已经注册有拦截器,则遍历拦截器
                             if (!ObjectUtils.isEmpty(interceptors)) {
                                 for (int i = 0; i < interceptors.length; i++) {
                                     HandlerInterceptor interceptor = interceptors[i];
                                     //如果注册拦截器的preHandle方法返回一个false,则该applyPreHandle方法就会返回false,从而在doDispatcher中的代码就不会往下执行了
                                     if (!interceptor.preHandle(request, response, this.handler)) {
                                         
                                         //这个方法要注意,它会调用所有已经成功执行的拦截器的afterCompletion方法,而且是反序调用的过程,可以分析triggerAfterCompletion
                                         //的源代码,主要是利用interceptorIndex反减的方式实现的。下面是源码的英文注释:
                                         //Trigger afterCompletion callbacks on the mapped HandlerInterceptors.
                                          //Will just invoke afterCompletion for all interceptors whose preHandle invocation
                                          //has successfully completed and returned true.
                                         triggerAfterCompletion(request, response, null);
                                         return false;
                                 }
                                     //没成功执行一个拦截器的preHandle方法,其interceptorIndex就会增加1;原始值为-1。
                                      this.interceptorIndex = i;
                                 }
                             }
                             return true;
                         }
                     *
                     *
                     *  顺带看看triggerAfterCompletion的源代码,很容易理解为什么拦截器的afterCompletion方法是反序执行的:
                     *    void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, Exception ex)
                                 throws Exception {
                    
                            HandlerInterceptor[] interceptors = getInterceptors();
                            if (!ObjectUtils.isEmpty(interceptors)) {
                                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);
                                    }
                                }
                            }
                        }
                     *
                     *
                     */
                    if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                        return;
                    }
    
                    // Actually invoke the handler.
                    /*
                     * 在这个函数里面会真正的执行request请求相对于的handler方法,可以想象:在真正调用方法之前还会有很多的
                     * 先前处理。在这里仅仅是分析出大概的代码执行流程,其细节的部分在后面的单独模块源码分析的时候做详细的讲解。
                     * 上面讲解到HandlerAdapter是一个接口:public interface HandlerAdapter,那么必然会有很多
                     * 中实现类,在采用注解@RequstMapping的方式标注handler的情况下,ha.handle方法会在底层调用具体的
                     * HandlerAdapter类实现方法RequestMappingHandlerAdapter.handleInternal
                     * 
                     * 分析一下RequestMappingHandlerAdapter.handleInternal的源代码:
                          protected ModelAndView handleInternal(HttpServletRequest request,
                            HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
                            //好像是看control的类定义处是否使用了@SessionAttributes注解,checkAndPrepare方法有什么作用???
                            if (getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
                                // Always prevent caching in case of session attribute management.
                                checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true);
                            }
                            else {
                                // Uses configured default cacheSeconds setting.
                                checkAndPrepare(request, response, true);
                            }
                            
                            // Execute invokeHandlerMethod in synchronized block if required.
                            // 这里是个值得注意的地方,synchronizeOnSession的值默认为false,如果通过某个方法使得其为true,那么request对应的handler
                            // 将会被放在同步快中进行处理。在什么时机下,使用什么方法才能将其设置为true呢???
                            if (this.synchronizeOnSession) {
                                HttpSession session = request.getSession(false);
                                if (session != null) {
                                    Object mutex = WebUtils.getSessionMutex(session);
                                    // 将handler放在同步块中处理
                                    synchronized (mutex) {
                                        return invokeHandleMethod(request, response, handlerMethod);
                                    }
                                }
                            }
                            //在invokeHandleMethod中会①将所有标注有@ModelAttrib的方法都执行一遍,②调用invokeAndHandle(webRequest, mavContainer)
                            //方法,在这里面调用handler方法,③最后调用getModelAndView(mavContainer, modelFactory, webRequest)方法的到ModelAndView。
                            //invokeHandleMethod这个方法还有很多东西要分析,留在后面。
                            //从上面的③我们可以看出,无论handler采用哪种模型化处理方式,最后都是将结果转化为ModelAndView
                            return invokeHandleMethod(request, response, handlerMethod);
                        }
                     */
                    mv = ha.handle(processedRequest, response,
                            mappedHandler.getHandler());
    
                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }
    
                    applyDefaultViewName(request, mv);
                    /*
                     * 调用request相关的拦截器的postHandle方法,注意,这个也是反序调用的。看看源代码:
                     *
                      void applyPostHandle(HttpServletRequest request, HttpServletResponse response, ModelAndView mv) throws Exception {
                            HandlerInterceptor[] interceptors = getInterceptors();
                            if (!ObjectUtils.isEmpty(interceptors)) {
                                //注意,这里也是反序执行,而且是所有成功执行了的postHandle拦截器
                                for (int i = interceptors.length - 1; i >= 0; i--) {
                                    HandlerInterceptor interceptor = interceptors[i];
                                    //这里传入的参数中有mv,也就是说,我们是有办法在拦截器的postHandle方法中修改已经返回的mv
                                    interceptor.postHandle(request, response, this.handler, mv);
                                }
                            }
                        }
                     */
                    mappedHandler.applyPostHandle(processedRequest, response, mv);
                } catch (Exception ex) {
                    dispatchException = ex;
                }
                processDispatchResult(processedRequest, response, mappedHandler,
                        mv, dispatchException);
            } catch (Exception ex) {
                triggerAfterCompletion(processedRequest, response, mappedHandler,
                        ex);
            } catch (Error err) {
                triggerAfterCompletionWithError(processedRequest, response,
                        mappedHandler, 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);
                    }
                }
            }
        }
    View Code

    http://www.cnblogs.com/lj95801/p/4961456.html?utm_source=tuicool&utm_medium=referral

    http://blog.csdn.net/initphp/article/details/37960327

    http://elim.iteye.com/blog/1750680

  • 相关阅读:
    java中原子操作的实现分析
    AQS源码分析
    Java JNDI 学习
    门面模式、代理模式、适配器模式的区别
    tomcat源码阅读之StandardWrapper解析
    tomcat源码阅读之过滤器
    tomcat源码阅读之SingleThreadModel
    tomcat源码阅读之单点登录
    技术人员的八条宝贵经验,时刻提醒自己,共勉之
    tomcat源码阅读之安全机制
  • 原文地址:https://www.cnblogs.com/hongdada/p/5960915.html
Copyright © 2011-2022 走看看