Skip to content

Latest commit

 

History

History
687 lines (550 loc) · 29.6 KB

SpringMVC源码分析.md

File metadata and controls

687 lines (550 loc) · 29.6 KB

Spring的源码分析

在分析SpringMVC源码之前我想先回顾一下JavaWeb的知识.JavaWeb的核心是Servlet,一个Servlet对应一个URL, 每次一个Http请求访问,那么对应URL的Servlet就会调用service方法处理。

其实这里我是对SpringMVC的一个复习,所以我先说说就我目前SpringMVC的理解吧。 大家都知道SpringMVC是一个MVC框架,但它还是脱离不了Tomcat,Undertow,Jetty这样的Servlet容器, 因为SpringMVC的核心还是是Servlet。

在初学SpringMVC的时候,各位同学可能都在web.xml里配置过DispatcherServlet,可能当时都没有想过为什么要去配置这个类, 甚至把它拦截的url配置成/**,我当时确实也没有想过,不过后来在学习的时候,已经明白了为什么这样去做, 并且已经明白了SpringMVC的设计思想。


前方高能

SpringMVC通过一个DispatcherServlet拦截所有请求,也就是url为 /** 。 通过拦截所有请求,在内部通过路由匹配的方式把请求转给对应Controller的某个RequestMapping处理。 这就是SpringMVC的基本工作流程,我们传统的JavaWeb是一个Servlet对应一个URL, 而DispatcherServlet是一个Servlet拦截全部URL,并做分发处理. 这也是SpringMVC的设计的精妙之处。

当然上面只是简单的一个流程,在这个过程中肯定有很多细节值得我们细细揣摩。

我是以SpringBoot搭建的调试环境,再加上已经知晓DispatcherServlet是核心, 几乎可以直接定位到这个类了,但是在这之前可以看看DispatcherServlet的父类:FrameworkServlet。 上面说过,Servlet是以service方法处理请求的,所以直接定位到FrameworkServlet的service方法:

    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpMethod httpMethod = HttpMethod.resolve(request.getMethod());
        if (httpMethod != HttpMethod.PATCH && httpMethod != null) {
            super.service(request, response);
        } else {
          
            //就是你了,骚年
            this.processRequest(request, response);
        
        }
    }

一个明显的方法 processRequest就进入了眼帘,看看这个processRequest做了什么吧:

    protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        ...
        try {

            //就是这个方法了
            this.doService(request, response);

        } catch (IOException | ServletException var16) {
            failureCause = var16;
            throw var16;
        } catch (Throwable var17) {
            failureCause = var17;
            throw new NestedServletException("Request processing failed", var17);
        } finally {
            this.resetContextHolders(request, previousLocaleContext, previousAttributes);
            if (requestAttributes != null) {
                requestAttributes.requestCompleted();
            }
            this.logResult(request, response, (Throwable)failureCause, asyncManager);
            this.publishRequestHandledEvent(request, response, startTime, (Throwable)failureCause);
        }

    }

可以看到一大坨代码都是try这个doService方法,而这个doService方法肯定是核心了, 但是这个doService方法在FrameworkServlet类中是个abstract方法,所以直接回到 DispatcherServlet找到doService方法:

    protected void doService(HttpServletRequest request, HttpServletResponse response) throws Exception {
        //...此处省略一大坨看不懂的代码
        try {
            //从这里开始分析
            this.doDispatch(request, response);

        } finally {
            if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted() && attributesSnapshot != null) {
                this.restoreAttributesAfterInclude(request, attributesSnapshot);
            }

        }

    }

已经找到了目标:doDispatch,听名字这个方法就是做事情的方法了, 所谓的做事情当然就是处理request了,如果各位同学学到现在, 肯定有一个意识:在SpringMVC框架中,所有的核心方法几乎都是do开头, 并且都有2个必要的参数:HttpServletRequest和HttpServletResponse.

但是DispatcherServlet是我接触的所有框架依赖不那么扯的, 就是这个doDispatch方法,它里面几乎包含了我们即将要学习的所有知识了, 所以接下来的核心就是doDispatch方法,各位同学在做源码阅读的时候,建议一行也不要放过(实在看不懂就别为难自己了^-^)。

不过在看DispatcherServlet源码之前,我们最后看下这个DispatcherServlet究竟何德何能, 能够这么厉害,可以完成我们几乎所有的需求方法:

public class DispatcherServlet extends FrameworkServlet {
    ....
    @Nullable
    private MultipartResolver multipartResolver;
    @Nullable
    private LocaleResolver localeResolver;
    @Nullable
    private ThemeResolver themeResolver;
    @Nullable
    private List<HandlerMapping> handlerMappings;
    @Nullable
    private List<HandlerAdapter> handlerAdapters;
    @Nullable
    private List<HandlerExceptionResolver> handlerExceptionResolvers;
    @Nullable
    private RequestToViewNameTranslator viewNameTranslator;
    @Nullable
    private FlashMapManager flashMapManager;
    @Nullable
    private List<ViewResolver> viewResolvers;
    ....
   }

这就是DispatcherServlet的九大组件,正是这九大组件, DispatcherServlet才能在支持请求和相应的同时,对许多功能和细节做出完善。

再看看doDispatch方法的源码,其实都是上面组件之间的配合完成任务:

    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpServletRequest processedRequest = request;

        //核心对象:HanderExecutorChain
        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;
                
                    //getHandler方法是根据请求获取对应的Controller和方法
                    mappedHandler = this.getHandler(processedRequest);

                    if (mappedHandler == null) {

                        //如果没有获取到匹配的handler,就要么抛出异常要么设置响应码404
                        this.noHandlerFound(processedRequest, response);
                        return;
                    }

                    //通过handler获取HandlerAdapter,由HandlerAdapter完成方法的执行
                    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 ((new ServletWebRequest(request, response)).checkNotModified(lastModified) && isGet) {
                            return;
                        }
                    }

                    //执行拦截器的preHandle方法,它内部如果执行不成功就会先执行afterCompletion,然后返回false,然后程序就退出
                    //这也是为什么拦截器的前置方法为什么返回false,程序就不会执行我们的逻辑了,等下会分析源码
                    if (!mappedHandler.applyPreHandle(processedRequest, response)) {
                        return;
                    }

                    //执行方法
                    mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

                    if (asyncManager.isConcurrentHandlingStarted()) {
                        return;
                    }

                    //根据Request使用RequestToViewNameTranslator设置默认的视图
                    this.applyDefaultViewName(processedRequest, mv);

                  //倒序执行拦截器的postHandle方法    
                    mappedHandler.applyPostHandle(processedRequest, response, mv);

                } catch (Exception var20) {
                    dispatchException = var20;
                } catch (Throwable var21) {
                    dispatchException = new NestedServletException("Handler dispatch failed", var21);
                }

                //解析并渲染ModelAndView
                this.processDispatchResult(processedRequest, response, mappedHandler, mv, (Exception)dispatchException);
          
            } catch (Exception var22) {

                //发生异常会倒序执行afterCompletion方法
                this.triggerAfterCompletion(processedRequest, response, mappedHandler, var22);

            } catch (Throwable var23) {

              //发生异常会倒序执行afterCompletion方法
                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);
            }

        }
    }

首先看看MultiPartResolver是如何检查文件上传请求的吧(checkMultipart方法):

    protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
       
        //关键在isMultpart方法
        if (this.multipartResolver != null && this.multipartResolver.  isMultipart(request)  ) {

            if (WebUtils.getNativeRequest(request, MultipartHttpServletRequest.class) != null) {
                if (request.getDispatcherType().equals(DispatcherType.REQUEST)) {
                    this.logger.trace("Request already resolved to MultipartHttpServletRequest, e.g. by MultipartFilter");
                }
            } else if (this.hasMultipartException(request)) {
                this.logger.debug("Multipart resolution previously failed for current request - skipping re-resolution for undisturbed error rendering");
            } else {
                try {
                   
                    //执行到这里就说明HttpServletRequest是一个文件上传请求,那么就把HttpServletRequest包装成
                    //MultpartHttpServletRequest返回
                    return this.multipartResolver.resolveMultipart(request);
               
                } catch (MultipartException var3) {
                    if (request.getAttribute("javax.servlet.error.exception") == null) {
                        throw var3;
                    }
                }

                this.logger.debug("Multipart resolution failed for error dispatch", var3);
            }
        }

        return request;
    }

先看看isMultiPart是怎么判断请求是否为文件上传请求的吧(isMultipart方法):

  public boolean isMultipart(HttpServletRequest request) {
        //判断Http请求包头的Content-Type
        return StringUtils.startsWithIgnoreCase(request.getContentType(), "multipart/");
    }

着重看看MultipartResolver是如何把普通请求包装成MultipartHttpServletRequest的吧(resolveMultipart方法):

  public MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException {
        //原来我们处理文件上传时拿到的请求是这个请求
        return new StandardMultipartHttpServletRequest(request, this.resolveLazily);
    }

从上面代码分析出,文件上传时,拿到的请求被包装成了StandardMultipartHttpServletRequest, 但是我不再深入,因为MultipartResolver是DispatcherServlet的一个 组件而已,再深入,就跑题了...也不是说跑题,毕竟都是SpringMVC的组成, 只是相信各位同学看到这里已经有能力去看看这个源码了, 可以明确的告诉各位这个地方不存在什么封装之类的曲折,单纯的就是 StandardMultipartHttpServletRequest内部对请求做了解析,并使用集合把解析的结果存储起来了而已 .

回到doDispatch方法,在执行完checkMultipart方法后,就通过getHandler方法, 获取了mappedHandler(HandlerExecutionChain)对象,这个HandlerExecutionChain是什么, 为什么getHandler返回它?先看看HandlerExecutionChain类的源码吧:

public class HandlerExecutionChain {
    private static final Log logger = LogFactory.getLog(HandlerExecutionChain.class);

    //handler,至于为什么设计成Object类型,我想可能是handler是执行method的关键,所以隐藏了细节,不对外暴露真实类型.
    //也有可能是在适配Controller的method的过程中需要多种类型的转换,总之不管哪种理由设计成Object类型,只有好好研究了.
    private final Object handler;

    @Nullable
    //一堆 HandlerInterceptor
    private HandlerInterceptor[] interceptors;

    @Nullable
    private List<HandlerInterceptor> interceptorList;
    private int interceptorIndex;

    public HandlerExecutionChain(Object handler) {
        this(handler, (HandlerInterceptor[])null);
    }
    ...
  }

这个HandlerExecutionChain包含了handler和它的所有HandleInterceptor.

再看看DispatcherServlet是如何根据HttpServletRequest获取HandlerExecutionChain的吧(getHandler方法):

    protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        if (this.handlerMappings != null) {

            //之前说过HandlerMapping是DispatcherServlet的9大组件之一,所以这里它遍历HandlerMapping来获取
            Iterator var2 = this.handlerMappings.iterator();

            while(var2.hasNext()) {
                HandlerMapping mapping = (HandlerMapping)var2.next();
              
                //调用HandlerMapping的getHandler方法来获取HandlerExecutionChain
                HandlerExecutionChain handler = mapping.getHandler(request);

                if (handler != null) {
                    return handler;
                }
            }
        }
        return null;
    }

继续看看HandlerMapping的getHandler怎么实现的:

    public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
        //首先就获取Handler
        Object handler = this.getHandlerInternal(request);

        if (handler == null) {
            handler = this.getDefaultHandler();
        }

        if (handler == null) {
            return null;
        } else {
            if (handler instanceof String) {
                String handlerName = (String)handler;
                handler = this.obtainApplicationContext().getBean(handlerName);
            }
        
            //这一步就构造了HandlerExecutionChain
            HandlerExecutionChain executionChain = this.getHandlerExecutionChain(handler, request);

            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Mapped to " + handler);
            } else if (this.logger.isDebugEnabled() && !request.getDispatcherType().equals(DispatcherType.ASYNC)) {
                this.logger.debug("Mapped to " + executionChain.getHandler());
            }

            if (this.hasCorsConfigurationSource(handler)) {
                CorsConfiguration config = this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(request) : null;
                CorsConfiguration handlerConfig = this.getCorsConfiguration(handler, request);
                config = config != null ? config.combine(handlerConfig) : handlerConfig;
                executionChain = this.getCorsHandlerExecutionChain(request, executionChain, config);
            }

            return executionChain;
        }
    }

在说上面一段代码之前,先回顾下, 之前介绍了HandlerExecutionChain由Handler和HandlerInterceptor组成, 那么我们就需要在getHandler里找到这2个关键的地方. 而第一行的getHandlerInternal方法就获取到了Handler, 后面又通过getHandlerExecutionChain直接构造出来了HandlerExecutionChain, 所以可以肯定:getHandlerInternal是根据URL映射找到了Handler getHandlerExecutionChain通过HandlerInterceptor和Handler构造了HandlerExecutionChain对象, 至于我为什么这么肯定, 自然是因为我已经阅读过了源码啦...这里留个空子,希望有缘看到这里的同学能够自己看看实现的细节.

回到doDispatch方法,在获取到handler(HandlerExecutionChain)后, 紧接着判断获取的handler是否为空,如果为空,说明url不对, 没有匹配的handler,就会调用noHandlerFound方法处理.

接下来 DispatcherServlet调用了getHandlerAdapter方法获取了又一个9大组件, 开始的时候介绍过:HandlerMapping是通过Request获取匹配的handler(HandlerExecutionChain)对象, 而HandlerAdapter才是指挥handler干活的, 所以这一步相当重要,看看这个getHandlerAdapter是如何获 HandlerAdapter的吧:

    protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
        if (this.handlerAdapters != null) {
            Iterator var2 = this.handlerAdapters.iterator();

            while(var2.hasNext()) {
                HandlerAdapter adapter = (HandlerAdapter)var2.next();
                //判断HandlerAdapter是否支持handler
                if (adapter.supports(handler)) {
                    return adapter;
                }
            }
        }

        throw new ServletException("No adapter for handler [" + handler + "]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler");
    }

可以看到getHandlerAdapter方法遍历DispatcherServlet的HandlerAdapter集合, 并且调用 HandlerAdapter 的 supports方法来选择合适的 HandlerAdapter,看看 supports 方法具体实现:

   public final boolean supports(Object handler) {
        //这里的主要是第一个判断: handler instanceof HandlerMethod
        return handler instanceof HandlerMethod && this.supportsInternal((HandlerMethod)handler);
    }

    //鉴于方便,我直接把supportsInternal方法贴过来
    protected boolean supportsInternal(HandlerMethod handlerMethod) {
        return true;
    }

可以看到supportsInternal方法对于HandlerMethod类型的参数直接返回true,当然这只是一个HandlerAdapter的实现,但也足够说明问题了,最重要的是第一个判断:

handler instanceof HandlerMethod 

我们之前说过handler在HandlerExecutionChain内部是一个Object类型, 到了这里为什么就变成了HandlerMethod类型了。 其实早在getHandler那一步就变成了Handler, 到这一步只是适配确认一下.那来看看HandlerMethod是什么吧, 它为什么可以执行我们的RequestMapping方法呢?

public class HandlerMethod {
    ...
    //bean既可以作为Controller,也可以作为Controller的name
    private final Object bean;
   
    //Controller所在的容器
    private final BeanFactory beanFactory;
   
    //Controller的 Class
    private final Class<?> beanType;
  
    //关键之处:requestmapping 对应的方法
    private final Method method;
   
    //桥接方法,我google了下,他是起兼容作用的,应该是与method有互补作用
    //这是那位大神的分析:[bregedmethod]( https://www.cnblogs.com/guangshan/p/4661305.html )
    private final Method bridgedMethod;
  
    //方法的参数
    private final MethodParameter[] parameters;
   
    //Http状态码
    private HttpStatus responseStatus;

    //不得不说Spring真是流比,像我等之流,只能仰望,返回状态码还得给个原因
    private String responseStatusReason;

    //保留的一份HandlerMethod,这个是解析当前HttpMethod实例的那个HttpMethod
    private HandlerMethod resolvedFromHandlerMethod;
    ....  
   }

其实到这里基本就知道SpringMVC到底是怎么通过反射执行我们的方法了, 还是不断的封装和反射,对于这些框架来说,万物皆可封装, 你不服就封装的你服,不管你服不服,我是服了.

再回到doDispatcher方法吧,这个时候已经获取到了需要的handler了, 那么就该执行拦截器的preHandle方法了吧,看接下来的applyPreHandle方法:

   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];

                //执行拦截器的preHandle方法,如果preHandle方法返回false,那么直接执行所有拦截器的afterCompletion方法
                if (!interceptor.preHandle(request, response, this.handler)) {
                    this.triggerAfterCompletion(request, response, (Exception)null);
                    return false;
                }
            }
        }
        return true;
    }

再回到doDispatcher方法,执行完拦截器的preHandle方法后 ,就直接调用HandlerAdapter的handle方法了:

  public final ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //调用了handleInternal方法
        return this.handleInternal(request, response, (HandlerMethod)handler);
    }
  
  //handleInteral方法
    protected ModelAndView handleInternal(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
        //检查是否支持请求的类型和是否需要session
        this.checkRequest(request);
       
        ModelAndView mav;
        if (this.synchronizeOnSession) {
            HttpSession session = request.getSession(false);
            if (session != null) {
                Object mutex = WebUtils.getSessionMutex(session);
                synchronized(mutex) {
                    //终于执行目标方法了 ~-~
                    mav = this.invokeHandlerMethod(request, response, handlerMethod);
                }
            } else {
                mav = this.invokeHandlerMethod(request, response, handlerMethod);
            }
        } else {
            mav = this.invokeHandlerMethod(request, response, handlerMethod);
        }

        if (!response.containsHeader("Cache-Control")) {
            if (this.getSessionAttributesHandler(handlerMethod).hasSessionAttributes()) {
                this.applyCacheSeconds(response, this.cacheSecondsForSessionAttributeHandlers);
            } else {
                this.prepareResponse(response);
            }
        }
        return mav;
    }

直接看 invokeHandlerMethod ,到底是如何执行method的:

    protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, HandlerMethod handlerMethod) throws Exception {
        ServletWebRequest webRequest = new ServletWebRequest(request, response);

        ModelAndView var15;
        try {
            WebDataBinderFactory binderFactory = this.getDataBinderFactory(handlerMethod);
            ModelFactory modelFactory = this.getModelFactory(handlerMethod, binderFactory);
            ServletInvocableHandlerMethod invocableMethod = this.createInvocableHandlerMethod(handlerMethod);
            if (this.argumentResolvers != null) {
                invocableMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
            }

            if (this.returnValueHandlers != null) {
                invocableMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
            }

            invocableMethod.setDataBinderFactory(binderFactory);
            invocableMethod.setParameterNameDiscoverer(this.parameterNameDiscoverer);
            ModelAndViewContainer mavContainer = new ModelAndViewContainer();
            mavContainer.addAllAttributes(RequestContextUtils.getInputFlashMap(request));
            modelFactory.initModel(webRequest, mavContainer, invocableMethod);
            mavContainer.setIgnoreDefaultModelOnRedirect(this.ignoreDefaultModelOnRedirect);
            AsyncWebRequest asyncWebRequest = WebAsyncUtils.createAsyncWebRequest(request, response);
            asyncWebRequest.setTimeout(this.asyncRequestTimeout);
            WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
            asyncManager.setTaskExecutor(this.taskExecutor);
            asyncManager.setAsyncWebRequest(asyncWebRequest);
            asyncManager.registerCallableInterceptors(this.callableInterceptors);
            asyncManager.registerDeferredResultInterceptors(this.deferredResultInterceptors);
            Object result;
            if (asyncManager.hasConcurrentResult()) {
                result = asyncManager.getConcurrentResult();
                mavContainer = (ModelAndViewContainer)asyncManager.getConcurrentResultContext()[0];
                asyncManager.clearConcurrentResult();
                LogFormatUtils.traceDebug(this.logger, (traceOn) -> {
                    String formatted = LogFormatUtils.formatValue(result, !traceOn);
                    return "Resume with async result [" + formatted + "]";
                });
                invocableMethod = invocableMethod.wrapConcurrentResult(result);
            }

            invocableMethod.invokeAndHandle(webRequest, mavContainer, new Object[0]);
            if (asyncManager.isConcurrentHandlingStarted()) {
                result = null;
                return (ModelAndView)result;
            }

            var15 = this.getModelAndView(mavContainer, modelFactory, webRequest);
        } finally {
            webRequest.requestCompleted();
        }

        return var15;
    }

上面这个代码...我哭了....^^^----^^^------^^^,总之我就看到了关于数据绑定, SpringMVC的异步核心管理器,ModelAndViewContainer(看名字就知道,容纳了当前handler的很多数据,恩...) 其实吧,我没哭,只是确实以我的功力, 还是有很多知识没有理解...好吧,我差点哭了.....(说好的轻量级框架呢?)

继续看doDispatcher,逻辑方法执行完了, RequestToViewNameTranslator 就会调用 applyDefaultViewName 方法设置默认的视图. 然后就会执行拦截器的 postHandle方法了:

    void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable 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];

                //执行postHandle方法
                interceptor.postHandle(request, response, this.handler, mv);
            }
        }

    }

最后,会通过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) {
                this.logger.debug("ModelAndViewDefiningException encountered", exception);
                mv = ((ModelAndViewDefiningException)exception).getModelAndView();
            } else {
                Object handler = mappedHandler != null ? mappedHandler.getHandler() : null;
                //通过HandlerExceptionResolver处理异常
                mv = this.processHandlerException(request, response, handler, exception);
                errorView = mv != null;
            }
        }

        if (mv != null && !mv.wasCleared()) {

            //通过View的render方法渲染视图
            this.render(mv, request, response);
            if (errorView) {
                WebUtils.clearErrorRequestAttributes(request);
            }
        } else if (this.logger.isTraceEnabled()) {
            this.logger.trace("No view rendering, null ModelAndView returned.");
        }

        if (!WebAsyncUtils.getAsyncManager(request).isConcurrentHandlingStarted()) {
            if (mappedHandler != null) {
                mappedHandler.triggerAfterCompletion(request, response, (Exception)null);
            }

        }
    }

这样一份源码也算是勉勉强强过了一遍,其实我发现从这个项目的第一份源码分析起到现在, 其中的一些知识不懂不是我笨,其实顺藤蘑摸瓜倒也好寻到一些线索。 只是像这样的框架我发现我根本没有去了解它的全貌.

我说一个现象:可能有很多同学在分析一份源码的时候, 不知道从哪就蹦出来一个比较陌生的对象,你知道它大概是干什么的, 与哪些你认识的类有关,但是你就是不知道它哪来了,久而久之,就会对这些框架形成敬畏感。 其实我确实对这些框架有敬畏感,毕竟从代码量和各种设计来说,就不得不有敬畏感, 到了他们这个体量,也很难再通过HelloWorld去了解他们的全貌了。

简单总结下SpringMVC工作的流程:

SpringMVC通过DispatcherServlet拦截所有的请求, 并通过HandlerMapping与指定的请求找出匹配的handler, handler实际是HandlerMethod对象。 再通过与handler适配的HandlerAdapter执行目标方法, 执行完目标方法后会返回ModelAndView对象, 最后通过ViewResolver解析ModelAndView的View视图。