文章目录
- 步步深入SpringMvc DispatcherServlet源码掌握springmvc全流程原理
- 继承关系
- 入口 DispatcherServlet#doDispatch
- 多文件上传解析
- 获取处理器
- handler的完整注册流程
- 获取HandlerAdapter
- 执行拦截器PreHandle
- 执行HandlerAdapter.handle
- 参数解析器HandlerMethodArgumentResolver
- @RequestBody的实现逻辑
- handler方法返回值处理器
- @ResponseBody的实现逻辑
- 执行拦截器postHandle
- 执行拦截器的afterCompletion
- 异常的处理
- Spring MVC 学习笔记深入源码
步步深入SpringMvc DispatcherServlet源码掌握springmvc全流程原理
继承关系
DispatcherServlet继承自最基础的HttpServlet
DispatcherServlet父类FrameworkServlet中实现了dotGet、doPost等do方法,都是调用了processRequest(request, response);
这方法里又调doService(request, response);
又调了doDispatch(request, response); 开始转发请求
入口 DispatcherServlet#doDispatch
多文件上传解析
processedRequest = checkMultipart(request);
代码就不贴了,很简单,自己可以点进去看,就检查method 为post,content type 是否以multipart/ 开头的,如果是则执行解析多文件上传请求,把文件封装为MultipartFile对象,设置在请求内部属性里MultiValueMap<String, MultipartFile> multipartFiles
获取处理器
mappedHandler = getHandler(processedRequest);
平时我们写的@RequestMapping(“/xxx”)就是这个接口的一个实现:RequestMappingHandlerMapping
打开这个类看可以看到Creates RequestMappingInfo instances from type and method-level @RequestMapping annotations in @Controller classes
注释写到 通过在@Controller类的方法中使用@RequestMapping来注册RequestMappingInfo实例
handler的完整注册流程
我们看下这个是怎么注册的,搜索RequestMappingHandlerMapping的使用,找到这个地方注入的,WebMvcAutoConfiguration,这个类在
spring-boot-autoconfigure-2.2.3.RELEASE.jar这个包里
先创建了RequestMappingHandlerMapping对象,再塞入拦截器等组件
而RequestMappingHandlerMapping继承了AbstractHandlerMethodMapping,AbstractHandlerMethodMapping这个实现了InitializingBean接口
在afterPropertiesSet方法里调用了初始化方法initHandlerMethods()
拿到上下文容器里的所有bean,逐个处理,执行processCandidateBean
判断这个bean是不是handler,如果是就执行detectHandlerMethods,去检测handler方法
对类中的方法逐个执行getMappingForMethod,去拿RequestMappingInfo,这个方法不是的话就返回的null
看下面两个代码图,你可以知道,是去检测了注解@RequestMapping,如果有就封装为RequestMappingInfo返回,没有就返回null。
最后全部扫描完,注册上去
可以看到最后其实就是放到了MappingRegistry类的属性map里存着了
获取HandlerAdapter
实际上内部就是逐个HandlerAdapter调了下supports方法看是不是支持,谁支持就返回谁
我们看到,这个handler适配器总共就只有几种的
我们这种HandlerMethod适用于这个适配器
执行拦截器PreHandle
循环执行这个methodHandler要使用的拦截器interceptor的preHandle
执行HandlerAdapter.handle
handle又直接调了handleInternal
执行invokeHandlerMethod
invokeHandlerMethod方法里把要的一些组件封装为一个ServletInvocableHandlerMethod,然后执行invocableMethod.invokeAndHandle(webRequest, mavContainer);
调用invokeForRequest执行请求
获取参数
参数解析器HandlerMethodArgumentResolver
@RequestBody的实现逻辑
参数解析器的接口,判断是否支持这个参数,以及解析参数的方法,有个常用的参数解析器,@RequestBody,我们探究下它的实现
查看实现类,搜body,就只剩这个了,进去看就是它
判断是否有注解@RequestBody
我们看这个readWithMessageConverters
又调用了readWithMessageConverters来使用MessageConverter解析消息,底层使用了MappingJackson2HttpMessageConverter来解析,这也是为啥直接写个对象,然后用@RequestBody注解就能解析好请求的Body参数。后面还会讲解@ResponseBody实现原理。
执行目标方法
handler方法返回值处理器
有个比较常见的返回值处理器就是RequestResponseBodyMethodProcessor
这个是HandlerMethodReturnValueHandler接口,用来对handler方法返回值做处理
@ResponseBody的实现逻辑
常用的@ResponseBody就是在这实现的
我们看下它的处理方法
继续进writeWithMessageConverters方法
我们看看HttpMessageConverter
就几个很简单的方法,能不能读,能不能写,读,写方法。看看实现类
我们看其中一个
继承了AbstractJackson2HttpMessageConverter,那四个接口方法都是在AbstractJackson2HttpMessageConverter实现的,我们去看看
内部使用的ObjectMapper来实现的读写
执行拦截器postHandle
执行拦截器的afterCompletion
执行异常拦截器、拦截器interceptors的afterCompletion
至此,HandlerInterceptor的preHandle、postHandle、afterCompletion全部执行完了
异常的处理
查看我的另一个异常专篇 springmvc 全局异常处理器配置的三种方式&深入底层源码分析原理
Spring MVC 学习笔记深入源码
Spring MVC 学习笔记深入源码