Spring源码分析: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方法有以下其他几种实现类:

扫描二维码关注公众号,回复: 12887100 查看本文章

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
在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/u012734723/article/details/107825624