原文链接:https://mp.weixin.qq.com/s/KX3-CJxhTqmjZYQ8Ei6lUQ
本文将通过阅读源码的方式带大家相识 springmvc 处置惩罚请求的完备流程,干货满满。
目录
- 1、先相识下 SpringMVC 常用的 10 组件
- 1.1、DispatcherServlet:前端控制器
- 1.2、HandlerMapping:处置惩罚器映射器
- 1.3、HandlerExecutionChain:处置惩罚器执行链
- 1.4、handler:处置惩罚器
- 1.5、HandlerAdapter:处置惩罚器适配器
- 1.6、ModelAndView:模型和视图
- 1.7、ViewResolver:视图解析器
- 1.8、View:视图
- 1.9、HandlerExceptionResolver:处置惩罚器异常解析器
- 1.10、HttpMessageConverter:http 报文转换器
- 2、处置惩罚流程:源码解析
- 2.1、请求到达入口:doDispatch
- 2.2、①:解析 multipart 类型的请求
- 2.3、②:根据请求获取 HandlerExecutionChain 对象
- 2.4、③:根据处置惩罚器获取 HandlerAdapter
- 2.5、④:调用拦截器的 preHandle 方法
- 2.6、⑤:调用 handler 现实处置惩罚请求,获取 ModelAndView 对象
- 2.7、⑥:调用拦截器的 postHandle 方法
- 2.8、⑦:渲染视图
- 3、处置惩罚流程:纯文字形貌
- 4、小结
- 5、案例代码
- 6、SpringMVC 系列
- 7、更多好文章
- 8、【路人甲 Java】所有系列高清 PDF
1、先相识下 SpringMVC 常用的 10 组件
1.1、DispatcherServlet:前端控制器
这个大家是最熟悉的,是一个 servlet,是 springmvc 处置惩罚请求的入口,不需要咱们开发,由框架提供。
作用:统一处置惩罚请求和相应,整个流程控制的中央,由它来调用其他组件处置惩罚用户的请求。
1.2、HandlerMapping:处置惩罚器映射器
作用:根据请求的信息(如 url、method、header 等)查找请求处置惩罚器,即找到自定义的 controller 中处置惩罚请求的方法。
HandlerMapping 接口源码如下,getHandler:根据请求查找请求处置惩罚器,会返回一个 HandlerExecutionChain 对象。
public interface HandlerMapping { HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception;}常见的实现类:
- RequestMappingHandlerMapping:请求映射处置惩罚器映射,用来处置惩罚@RequestMapping 定义的处置惩罚器的
1.3、HandlerExecutionChain:处置惩罚器执行链
HandlerMapping#getHandler 方法会根据请求得到一个 HandlerExecutionChain 对象。
HandlerExecutionChain 源码如下,主要包罗了 3 个信息
- handler:请求处置惩罚器,通常就是我们自定义的 controller 对象及方法
- interceptorList:拦截器,当前请求匹配到的拦截器列表
- interceptorIndex:拦截器索引,用来记录执行到第几个拦截器了
public class HandlerExecutionChain { private final Object handler; private final List interceptorList = new ArrayList(); private int interceptorIndex = -1;}1.4、handler:处置惩罚器
通常需要我们自己开发,一般指我们自定义的 controller,在 DispatcherServlet 的控制下 handler 对具体的请求举行处置惩罚。
1.5、HandlerAdapter:处置惩罚器适配器
他负责对 handler 的方法举行调用,由于 handler 的类型大概有很多种,每种 handler 的调用过程大概不一样,此时就需要用到适配器 HandlerAdapte,适配器对外暴露了统一的调用方式(见其 handle 方法),内部将 handler 的调用过程屏蔽了,HandlerAdapter 接口源码如下,主要有 2 个方法需要留意:
- supports:当前 HandlerAdapter 是否支持 handler,其内部主要就是判 HandlerAdapter 是否能够处置惩罚 handler 的调用
- handle:其内部负责调用 handler 的来处置惩罚用户的请求,返回返回一个 ModelAndView 对象
public interface HandlerAdapter { boolean supports(Object handler); @Nullable ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception;}常见的实现类:
- RequestMappingHandlerAdapter:其内部用来调用@RequestMapping 标注的方法
1.6、ModelAndView:模型和视图
这个对象中主要用来存放视图的名称和共享给客户端的数据。
public class ModelAndView { /*视图*/ @Nullable private Object view; /*模型,用来存放共享给客户端的数据*/ @Nullable private ModelMap model;}1.7、ViewResolver:视图解析器
这个是框架提供的,不需要咱们自己开发,它负责视图解析,根据视图的名称得到对应的视图对象(View)。
ViewResolver 接口源码
public interface ViewResolver { @Nullable View resolveViewName(String viewName, Locale locale) throws Exception;}这个接口有很多实现类,比如 jsp 的、freemarker、thymeleaf 的等,他们都有各自对应的 ViewResolver。
而比较常的实现类是InternalResourceViewResolver,这个大家应该比较熟悉吧,目前为止我们前面的文章用到的都是这个视图解析器,用来处置惩罚 jsp 格式的视图页面,带大家再回顾一下这个类的配置,如下
InternalResourceViewResolver 比较重要,这里说下这个类的 resolveViewName 方法获取视图的过程,大家也可以去阅读InternalResourceViewResolver#resolveViewName方法得到,大致的过程如下:
step1:判断视图 viewName 是否以redirect:开头,假如是,则返回RedirectView类型的视图对象,RedirectView 是用来重定向的,RedirectView 内部用到的是response.sendRedirect(url)举行页面重定向;否则继续向下 step2
step2:判断 viewName 是否以forward:开头,假如是,则返回InternalResourceView类型的视图对象,InternalResourceView 是用来做跳转的,InternalResourceView 内部用到的是request.getRequestDispatcher(path).forward(request, response)举行页面跳转;否则继续向下 step3
step3:判断当前项目是否存在 jstl 所需的类,假如是,则返回 JstlView 类型的视图,否则返回 InternalResourceView 类型的视图,这两个视图的 render 方法终极会通过request.getRequestDispatcher(path).forward(request, response)举行页面的跳转,跳转的路径是:InternalResourceViewResolver 的前缀 prefix + viewName+InternalResourceViewResolver 的后缀 prefix
1.8、View:视图
负责将结果展示给用户,View 接口源码如下,render 方法根据指定的模型数据(model)渲染视图,即 render 方法负责将结果输出给客户端。
public interface View { void render(@Nullable Map model, HttpServletRequest request, HttpServletResponse response) throws Exception;}View 接口常见的 2 个实现类
- RedirectView:负责重定向的,内部通过response.sendRedirect(url)举行页面重定向
- InternalResourceViewResolver:负责页面跳转的,内部通过request.getRequestDispatcher(path).forward(request, response)举行页面的跳转
1.9、HandlerExceptionResolver:处置惩罚器异常解析器
负责处置惩罚异常的,HandlerExceptionResolver 接口有个resolveException方法,用来解析异常,返回异常环境下对应的 ModelAndView 对象
public interface HandlerExceptionResolver { @Nullable ModelAndView resolveException( HttpServletRequest request, HttpServletResponse response, @Nullable Object handler, Exception ex);}1.10、HttpMessageConverter:http 报文转换器
将请求报文转换为 Java 对象,或将 Java 对象转换为相应报文,在处置惩罚@RequestBody、RequestEntity、@ResponseBody、ResponseEntity 的时候会用到
public interface HttpMessageConverter { /** * 是否可以将请求保温读取给方法参数指定的类型 */ boolean canRead(Class clazz, @Nullable MediaType mediaType); /** * 是否可以将相应的保温转换为方法参数指定的类型输出 */ boolean canWrite(Class clazz, @Nullable MediaType mediaType); /** * 当前转换器支持的类型 */ List getSupportedMediaTypes(); /** * 当前转换器支持的类型 */ default List getSupportedMediaTypes(Class clazz) { return (canRead(clazz, null) || canWrite(clazz, null) ? getSupportedMediaTypes() : Collections.emptyList()); } /** * 将http保温转换为给定的类型,然后返回 */ T read(Class |