万字长文,深度解析SpringMVC 源码,让你醍醐灌顶
原文链接: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 转发了
页:
[1]