程序猿阿嘴 潜水
  • 5发帖数
  • 5主题数
  • 0关注数
  • 0粉丝
开启左侧

万字长文,深度解析SpringMVC 源码,让你醍醐灌顶

[复制链接]
程序猿阿嘴 发表于 2021-9-14 13:53:39 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
原文链接: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

牧涯475 发表于 2021-9-14 18:51:51 | 显示全部楼层
转发了
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

猜你喜欢
在线客服邮箱
wxcy#wkgb.net

邮箱地址#换为@

Powered by 创意电子 ©2018-现在 专注资源实战分享源码下载站联盟商城