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

posted @ 2016-10-14 16:13  hongdada  阅读(724)  评论(0编辑  收藏  举报