请求流程
SpringMVC 的整个请求流程 ^2
- 用户请求发送到前端控制器DispatcherServlet
- 前端控制器DispatcherServlet接收到请求后,DispatcherServlet会使用HandlerMapping来处理,HandlerMapping会查找到具体进行处理请求的Handler对象
- HandlerMapping找到对应的Handler之后,返回一个Handler执行链,在这个执行链中包括了拦截器和处理请求的Handler
- DispatcherServlet接收到执行链之后,会调用Handler适配器去执行Handler
- Handler适配器执行完成Handler(也就是我们写的Controller)之后会得到一个ModelAndView,并返回给DispatcherServlet
- DispatcherServlet接收到Handler适配器返回的ModelAndView之后,会根据其中的视图名调用视图解析器
- 视图解析器根据逻辑视图名解析成一个真正的View视图,并返回给DispatcherServlet
- DispatcherServlet接收到视图之后,会根据上面的ModelAndView中的model来进行视图中数据的填充,也就是所谓的视图渲染
- 渲染完成之后,DispatcherServlet就可以将结果返回给用户了
- 说明
- springboot直接使用Servlet,这种请求是不会进入SpringMVC的流程的
请求进入DispatcherServlet
- FrameworkServlet.java
1 | // DispatcherServlet 继承自 FrameworkServlet,请求先进入到 service 方法 |
- DispatcherServlet.java
1 | // 实现 FrameworkServlet 的抽象方法 |
查找请求对应的Handler对象(Controller)
- DispatcherServlet.java
1 |
|
- AbstractHandlerMapping.java
1 |
|
- 以 AbstractHandlerMethodMapping.java 为例
1 |
|
- 如果是使用@RequestMapping(如SpringBoot中),则通过RequestMappingInfoHandlerMapping.java可解析出Handle(继承自AbstractHandlerMethodMapping)
1 |
|
- AbstractHandlerMapping.java
1 | protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) { |
获取对应请求的Handler适配器
1 | protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException { |
系统初始化
mappingRegistry初始化
- mappingRegistry主要记录了URL-HandlerMethod(Controller方法)的映射
- 映射处理器HandlerMapping接口说明,参考spring.md#映射处理器HandlerMapping
- AbstractHandlerMapping(实现getHandler方法)
- AbstractHandlerMethodMapping(通过MappingRegistry初始化URL-HandlerMethod映射)
- 对应的实现类
- RequestMappingHandlerMapping 处理@RequestMapping
- SimpleUrlHandlerMapping 简单的urlMap保存了URL到HttpRequestHandler的映射
- BeanNameUrlHandlerMapping 将bean的name作为url进行查找,需要在配置Handler时指定bean name,且必须以 / 开头
- 还可自定义
MappingRegistry类说明
1 | public abstract class AbstractHandlerMethodMapping<T> extends AbstractHandlerMapping implements InitializingBean { |
MVC请求参数解析
@RequestParam
可以获取GET请求、POST请求的Param参数(添加到URL中的参数,无法获取Body中的数据)- 其required属性默认为true,即必须传入此参数,否则报错;可设置required=false做成可选参数
@RequestBody
仅适用于获取POST请求的Body数据(可以是json/txt等格式)- 使用参考:springboot.md#请求参数字段映射
类关系
- org.springframework.web.method
- InvocableHandlerMethod 参数处理器
- HandlerMethodArgumentResolver 参数解析器
- RequestParamMethodArgumentResolver 处理 @RequestParam 注解, @RequestPart 注解, Multipart 类型的参数
- ModelAttributeMethodProcessor
- ServletModelAttributeMethodProcessor 处理无注解的普通Bean
- RequestResponseBodyMethodProcessor 处理 @RequestBody 注解的参数(数据在请求body中,常见的会定义body数据格式为application/json,最终通过 AbstractJackson2HttpMessageConverter 解析)
- org.springframework.web.bind
- WebDataBinder 解析参数时,对request参数绑定到方法参数中
- ServletRequestDataBinder
- WebDataBinder 解析参数时,对request参数绑定到方法参数中
- org.springframework.beans
- TypeConverterDelegate 类型转换代理
- org.springframework.core
- GenericConverter 转换器模型接口(实际转换一般通过调用 ConversionService 实现)
- ConversionService 转换器逻辑接口
- GenericConversionService
- addConverter 实现了 ConverterRegistry 接口,如 WebMvcAutoConfiguration#addFormatters 可添加转换器
- FormattingConversionService 处理Bean的Format字段注解,如:
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
(最终通过 TemporalAccessorParser 实现转换)
- GenericConversionService
- ConverterRegistry 转换器注册接口
- org.springframework.http
- HttpMessageConverter 接口
- GenericHttpMessageConverter 接口
- AbstractJackson2HttpMessageConverter 最终通过 ObjectMapper(可进行自定义映射规则)进行转换
- MappingJackson2HttpMessageConverter 通过Jackson解析application/json格式数据
- AbstractJackson2HttpMessageConverter 最终通过 ObjectMapper(可进行自定义映射规则)进行转换
- GenericHttpMessageConverter 接口
- HttpMessageConverter 接口
流程
- 参考 ^1
1 | // 测试方法 |
参考文章