MVC调用过程
注意:需要配置load-on-startup属性值为1才会在容器启动的时候初始化DispatcherServlet,不然会在第一次发起Controller请求时才初始化DispatcherServlet
容器启动初始化DispatcherServlet(中央控制器)
DispatcherServlet继承FrameworkServlet,FrameworkServlet继承HttpServletBean
调用HttpServletBean的init方法,将配置参数映射到该servlet的bean属性上,并调用子类初始化,如果bean属性无效(或缺少必需的属性),或者子类初始化失败,抛出ServletException。
init方法会调用子类FrameworkServlet覆写的initServletBean的方法。初始化并发布此Servlet的WebApplicationContext。委托createWebApplicationContext方法进行实际的上下文创建。 可以在子类中覆盖。
手动触发初始onRefresh。
DispatcherServlet覆写了FrameworkServlet的onRefresh方法。
初始化此servlet使用的策略对象。可以在子类中重写以初始化其他策略对象。
initHandlerMappings方法初始化ApplicationContext(应用上下文)使用的HandlerMappings。如果在BeanFactory中没有为此名称空间定义HandlerMapping Bean,则默认使用BeanNameUrlHandlerMapping。Spring在DispatcherServlet.properties中设置了默认值。
初始化ApplicatioContext(应用上下文)使用的HandlerAdapters。如果在BeanFactory中没有为此名称空间定义HandlerAdapter Bean,则默认为SimpleControllerHandlerAdapter。
初始化应用上下文使用的异常解析器。
初始化此servlet实例使用的RequestToViewNameTranslator。如果未配置任何实现,则默认为DefaultRequestToViewNameTranslator。
初始化应用上下文使用的ViewResolvers。如果没有为此在BeanFactory中定义ViewResolver Bean
命名空间,我们默认使用InternalResourceViewResolver。
DispatcherServlet处理Request请求
进入doService方法设置DispatcherServlet的属性,和调用doDispatch方法将请求交给处理器处理。
判断请求是否是文件上传
如果请求是属于文件上传,就将request封装成一个MultipartHttpServletRequest。
调用StandardServletMultipartResolver的isMultipart方法判断是否是文件上传Request。如果请求方法不是Post,返回false。如果请求数据的格式不是multipart开头,返回false,否则,返回true。
获取处理器映射器HandlerMapping
HandlerMapping类有一个getHandler方法,返回值是HandlerExecutionChain(执行链)。HandlerExecutionChain类有变量:handler、interceptors和interceptorList
HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;
AbstractHandlerMapping的getHandler方法,先是获取到request的HandlerMethod对象,再获取到HandlerExecutionChain(执行链)。
AbstractHandlerMethodMapping的getHandlerInternal方法查找给定request请求的处理方法。先获取读写锁的读锁,获取处理方法,释放读锁。
查找当前请求的最佳匹配处理程序方法。
进入AbstractHandlerMapping的getHandlerExecutionChain方法,获取执行链,同时添加执行链的拦截器。
获取处理器适配器HandlerAdapter
调用supports方法判断handler的类型
这里调用的是AbstractHandlerMethodAdapter的supports方法。
RequestMappingHandlerAdapter继承AbstractHandlerMethodAdapter,AbstractHandlerMethodAdapter继承HandlerAdapter。
判断对象是否属于HandlerMethod,supportsInternal方法默认返回true。
HandlerAdapter的supports方法有以下其他几种实现类:

SimpleControllerHandlerAdapter
判断对象是否属于Controller
SimpleServletHandlerAdapter
判断对象是否属于Servlet
HttpRequestHandlerAdapter
判断对象是否属于HttpRequestHandler
浏览器缓存
RequestMappingHandlerAdapter的getLastModifiedInternal的值返回-1,是为了计算lastModified值,
ServletWebRequest的checkNotModified方法。
如果调用validateIfUnmodifiedSince方法返回true,并且notModified的值是true,就会设置响应的状态码为Precondition Failed(412)
这里调用validateIfUnmodifiedSince值是-1,所以直接返回false;notModified的默认值是false。
直接返回false。
调用拦截器的前置处理器
应用注册拦截器的preHandle方法。
获取全部的拦截器,调用每个拦截器的preHandle方法,如果某个拦截器返回值是false,会调用该拦截器的afterCompletion方法,然后整个调用停止,也不会再执行后面的业务逻辑。
获取调用方法的返回值
先获取调用方法的入参,InvocableHandlerMethod的doInvoke方法使用反射调用请求request对应的类的方法。最后拿到业务方法的返回值。
getBridgedMethod方法的值是:public com.alibaba.fastjson.JSONObject gdut.ff.controller.BlogController.findAllBlogs(gdut.ff.domain.Blog)
getBean方法的值是:
args的值是:
然后会进入到我的业务方法:
处理获得的返回值
调用HandlerMethodReturnValueHandlerComposite的handleReturnValue方法获取到的HandlerMethodReturnValueHandler类型是RequestResponseBodyMethodProcessor,因为我业务方法的返回值是JSONObject。
调用拦截器的后置处理器
执行拦截器的后置处理器postHandle方法。
异常判断&&模板渲染&&执行拦截器的afterCompletion方法
异常分为ModelAndViewDefiningException和其他异常
渲染ModelAndView模板,因为我这里返回的是一个JSONObject,所以不会执行这一步。
执行拦截器的afterCompletion方法。
参考资料
https://www.bilibili.com/video/BV1WC4y1h7So?p=32&t=5428