加入收藏 | 设为首页 | 会员中心 | 我要投稿 东莞站长网 (https://www.0769zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 教程 > 正文

SpringMVC 拦截器源码介绍

发布时间:2021-11-12 12:08:14 所属栏目:教程 来源:互联网
导读:前言:这两天学习了代理模式,自然想到了SpringMVC 的 AOP 使用的就是动态代理,拦截器使用的就是 jdk 的动态代理。今天看了看源码,记录一下。SpringMVC 的拦截器使用移步:Java Servlet 过滤器与 SpringMVC 拦截器的区别? 源码解析 springMVC 的所有连接

前言:这两天学习了代理模式,自然想到了SpringMVC 的 AOP 使用的就是动态代理,拦截器使用的就是 jdk 的动态代理。今天看了看源码,记录一下。SpringMVC 的拦截器使用移步:Java Servlet 过滤器与 SpringMVC 拦截器的区别?
 
源码解析
 
  springMVC 的所有连接入口都会进入 DispatcherServlet,然后在这里面去调用真正的 Controller。而拦截器要达到的作用则是在调用 Controller 前后去做一些事情。所以现在需要看看 DispatcherServlet 的源码。
 
DispatcherServlet
 
  DispatcherServlet 的源码入口在 doService() 方法。
 
protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
        if(this.logger.isDebugEnabled()) {
            String resumed = WebAsyncUtils.getAsyncManager(request).hasConcurrentResult()?" resumed":"";
            this.logger.debug("DispatcherServlet with name '" + this.getServletName() + "'" + resumed + " processing " + request.getMethod() + " request for [" + getRequestUri(request) + "]");
        }
 
        Map<String, Object> attributesSnapshot = null;
        if(WebUtils.isIncludeRequest(request)) {
            attributesSnapshot = new HashMap();
            Enumeration attrNames = request.getAttributeNames();
 
            label108:
            while(true) {
                String attrName;
                do {
                    if(!attrNames.hasMoreElements()) {
                        break label108;
                    }
 
                    attrName = (String)attrNames.nextElement();
                } while(!this.cleanupAfterInclude && !attrName.startsWith("org.springframework.web.servlet"));
 
                attributesSnapshot.put(attrName, request.getAttribute(attrName));
            }
        }
 
        request.setAttribute(WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.getWebApplicationContext());
        request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, this.localeResolver);
        request.setAttribute(THEME_RESOLVER_ATTRIBUTE, this.themeResolver);
        request.setAttribute(THEME_SOURCE_ATTRIBUTE, this.getThemeSource());
        FlashMap inputFlashMap = this.flashMapManager.retrieveAndUpdate(request, response);
        if(inputFlashMap != null) {
            request.setAttribute(INPUT_FLASH_MAP_ATTRIBUTE, Collections.unmodifiableMap(inputFlashMap));
        }
 
        request.setAttribute(OUTPUT_FLASH_MAP_ATTRIBUTE, new FlashMap());
        request.setAttribute(FLASH_MAP_MANAGER_ATTRIBUTE, this.flashMapManager);
 
        try {
            this.doDispatch(request, response);
        } finally {
            if(!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot != null) {
                this.restoreAttributesAfterInclude(request, attributesSnapshot);
            }
 
        }
 
    }
 
  doService() 方法里面处理了一些信息之后,调用了 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 {
            try {
                ModelAndView mv = null;
                Object 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 ha = this.getHandlerAdapter(mappedHandler.getHandler());
                    String method = request.getMethod();
                    boolean isGet = "GET".equals(method);
                    if(isGet || "HEAD".equals(method)) {
                        long lastModified = ha.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;
                        }
                    }
 
                    if(!mappedHandler.applyPreHandle(processedRequest, response)) {
                        return;
                    }
 
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
                    if(asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }
 
                    this.applyDefaultViewName(processedRequest, mv);
                    mappedHandler.applyPostHandle(processedRequest, response, mv);
                } catch (Exception var20) {
                    dispatchException = var20;
                } catch (Throwable var21) {
                    dispatchException = new NestedServletException("Handler dispatch failed", var21);
                }
 
                this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
            } catch (Exception var22) {
                this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);
            } catch (Throwable var23) {
                this.triggerAfterCompletion(processedRequest, response, mappedHandler, new NestedServletException("Handler processing failed", var23));
            }
 
        } finally {
            if(asyncManager.isConcurrentHandlingStarted()) {
                if(mappedHandler != null) {
                    mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
                }
            } else if(multipartRequestParsed) {
                this.cleanupMultipart(processedRequest);
            }
 
        }
    }
 
  doDispatch() 方法中通过 this.getHandler(processedRequest); 获取到了处理器链 HandlerExecutionChain mappedHandle 之后,去执行了  mappedHandler.applyPreHandle(processedRequest, response) 方法,从而执行了拦截器的 preHandle 方法,如果返回为 false,则会调用处理器链的 triggerAfterCompletion 方法,然后 DispatchServlet 类中会直接 retreturn;如果返回为 true,则继续。
 
  然后调用了 HandlerAdapter 的 handler() 方法;
 
  然后调用了 mappedHandler.applyPostHandle(processedRequest, response, mv); 方法,从而执行了拦截器的 postHandle 方法;
 
  然后调用了 this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException); 方法;在 processDispatchResult() 方法里面渲染了对应的视图,然后调用了 mappedHandler.triggerAfterCompletion(request, response, (Exception)null); 方法,从而执行了拦截器的 afterCompletion 方法。
 
  processDispatchResult() 源码如下:
 
    private void processDispatchResult(HttpServletRequest request, HttpServletResponse response, HandlerExecutionChain mappedHandler, ModelAndView mv, Exception exception) throws Exception {
        boolean errorView = false;
        if(exception != null) {
            if(exception instanceof ModelAndViewDefiningException) {
                this.logger.debug("ModelAndViewDefiningException encountered", exception);
                mv = ((ModelAndViewDefiningException)exception).getModelAndView();
            } else {
                Object handler = mappedHandler != null?mappedHandler.getHandler():null;
                mv = this.processHandlerException(request, response, handler, exception);
                errorView = mv != null;
            }
        }
 
        if(mv != null && !mv.wasCleared()) {
            this.render(mv, request, response);
            if(errorView) {
                WebUtils.clearErrorRequestAttributes(request);
            }
        } else if(this.logger.isDebugEnabled()) {
            this.logger.debug("Null ModelAndView returned to DispatcherServlet with name '" + this.getServletName() + "': assuming HandlerAdapter completed request handling");
        }
 
        if(!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
            if(mappedHandler != null) {
                mappedHandler.triggerAfterCompletion(request, response, (Exception)null);
            }
 
        }
    }
 
  从 doDispatch() 方法这里主要需要知道 HandlerExecutionChain mappedHandler = this.getHandler(processedRequest); 这一句调用的 getHandler() 方法,源码如下。
 
  getHandle() 方法里是通过 HandlerMapping 的 getHandler 方法返回 HandlerExecutionChain 的。
 
  从代码中不难看出整个逻辑就是依次判断 servlet 中的每个 handlerMapping 是否能够匹配该请求,直到找到那个匹配的然后返回处理结果。
 
    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        Iterator var2 = this.handlerMappings.iterator();
 
        HandlerExecutionChain handler;
        do {
            if(!var2.hasNext()) {
                return null;
            }
 
            HandlerMapping hm = (HandlerMapping)var2.next();
            if(this.logger.isTraceEnabled()) {
                this.logger.trace("Testing handler map [" + hm + "] in DispatcherServlet with name '" + this.getServletName() + "'");
            }
 
            handler = hm.getHandler(request);
        } while(handler == null);
 
        return handler;
    }
 
HandlerExecutionChain 类
 
  applyPreHandle() 方法源码如下:可以看出是顺序调用拦截器的 preHandle() 方法。preHandle 返回 false 时调用了 triggerAfterCompletion 方法。
 
    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;
    }
 
  applyPostHandle() 方法源码如下:可以看出这里是逆序调用 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);
            }
        }
 
    }
 
 triggerAfterCompletion() 方法源码如下:可以看出这里也是逆序调用 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);
                }
            }
        }
 
    }

(编辑:东莞站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读