一、SpringMVC 执行原理

SpringMVC 的设计是围绕 DispatcherServlet 展开的,DispatcherServlet 负责将请求派发到特定的 Controller,Controller 返回的结果经过 ViewReolver 解析得到对应的视图 或者 视图对象等,体现出 MVC 模式

  1. 用户对服务器发送请求,请求被 前端控制器 DispatcherSevlet 所捕获。
  2. DispatcherSevlet 会对请求的 URL 进行解析,得到请求资源标识符 (URI) 。然后根据请求的 URI,调用 HandlerMapping (映射处理器) 获得该 Handler 配置的所有相关对象 (包括 Handler 对象 以及 Handler 对象对应的拦截器)。 最后返回 HandlerExecutionChain 对象。
  3. DispatcherServlet 根据获得的 Handler,选择一个合适的 HandlerAdapter (处理适配器)。执行相对应的 Controller (如果完成了 HandlerAdapter 后,此后将执行拦截器的 preHandler(..) 方法。
  4. 提取 Raequest 中的模型数据,填充 Handler 入参,开始执行 Handler(Controller)。在填充过程中,根据配置,Spring 会为我们做一些额外的工作

    1. HttpMessageConveter:
      1. 将请求消息 (如 json,xml 等数据)转换为一个对象 ,将对象转换为指定的响应消息。
      2. 数据转换:对请求消息进行数据转换 (如 String 转换为 Integer,Double 等)
      3. 数据格式化:对请求消息进行数据格式化。如将字符串转换成格式化数字或格式化日期等。
      4. 数据验证:验证数据的有效性(长度、格式等),验证结果存储到 BindingResult 或 Error 中
  5. Handler 执行完成后,向 DispatcherServlet 返回一个 ModelAbdView 对象

  6. 根据返回的 ModelAndView,选择一个合适的 ViewResolver(视图解析器),必须已经注册到 Spring 容器中 ViewResolver 返回给 DispatcherServlet
  7. ViewResolver 结合 Model 和 View,来渲染视图。
  8. 将渲染结果返回给前端。

二、核心控制器 DispatcherSevlet

  • DispatcherSevlet 是 前端控制器设计模式的实现,提供了 Spring Web MVC的集中访问点,而且负责职责的分派,与 Spring IoC 容器无缝集成,从而可以获得 Spring 特性带来的好处。

2.1 核心工作职责

  • DispatcherServlet 主要用作职责调度工作,本身用于控制流程

    • 负责文件上传解析,如果请求类型是 multipart 将通过 MultipartResolver 进行文件上传解析
    • 通过 HandlerMapping,将请求映射到处理器(返回一个 HandlerExecutionChain,它包括一个 Handler 处理器,多个 HandlerInterceptor 拦截器)
    • 通过 HandlerAdapter 支持多种类型的处理器 (HandlerExecutionChain 中的处理器)
    • 通过 ViewResolver 解析逻辑视图名到具体视图实现。
    • 本地化解析
    • 渲染具体视图等
    • 如果执行过程中遇到异常将交给 HandlerExceptionResolver 来解析
  • DispatcherServlet 在流程中每个关键点都是 很容易扩展

2.2 核心控制器中 Bean 对象的工作职责

  • DispatcherServlet默认使用WebApplicationContext作为上下文,该上下文中有一些特殊的 Bean

**

- Controller

处理器/页面控制器,做的是 MVC 中 C 的事情,但控制逻辑转移给 前端控制器 了,用于对请求进行处理。

- HandlerMapping

请求处理器的映射,如果映射成功,返回一个 HandlerExecutionChain (括一个 Handler 处理器,多个 HandlerInterceptor 拦截器),如 BeanNameUrlHandlerMapping 将URL与Bean名字映射,映射成功的Bean就是此处的处理器

补充:
此处指的 Handler 处理器有两类:

  1. BeanNameUrlHandlerMapping
    1. 实现 Controller 接口的控制器会使用该处理器
    2. 实现 httpRequestHandler 接口的控制器也会使用该处理器
  2. RequestMappingHandlerMapping
    1. 使用注解式的控制器会使用该处理器

**

- HandlerAdapter

HandlerAdapter 将会把 处理器 包装成 适配器, 从而支持多种类型的的处理器,即 适配器设计模式 的应用,从而很容易支持多种类型的处理器,如 SimpleControllerHandlerAdapter 将对实现了 Controller 接口的 Bean 进行适配,并处理掉处理器的 handleRequest 方法进行功能处理。

补充:

  1. 实现了 Controller 接口的控制器 会使用 SimpleControllerHandlerAdapter 进行适配
  2. 实现了 HttpRequestHandler 接口控制器,会使用 HttpRequestHandlerAdapter 进行适配
  3. 使用了注解方式的控制器,会使用 requestMappingHandlerAdapter 进行适配


- Controller —> HandlerMapping —> HandlerAdapter 图解

image.png

- ViewResolver

ViewResolver 将把 逻辑视图名 解析为具体的 View,通过这种策略模式,很容易更换其他视图技术,如 InternalResourceViewResolver 将逻辑视图名映射为 JSP 视图

- LocalResover

本地化解析,因为 Spring 支持国际化,因此 LocalResover 解析客户端的 Locale 信息从而方便的进行国际化

- ThemeResovler

•主题解析,通过它来实现一个页面多套风格,即常见的类似于软件皮肤效果;

- MultipartResolver:

文件上传解析,用于支持文件上传;

- HandlerExceptionResolver:

处理器异常解析,可以将异常映射到相应的统一错误界面,从而显示用户友好的界面(而不是给用户看到具体的错误信息);
**

- RequestToViewNameTranslator:

•处理器没有返回逻辑视图名等相关信息时,自动将请求URL映射为逻辑视图名;
**

- FlashMapManager:

•用于管理FlashMap的策略接口,FlashMap用于存储一个请求的输出,当进入另一个请求时作为该请求的输入,通常用于重定向场景;

2.3 SpringMVC中上下文的关系

  • Spring 的上下文是 Servlet 的 application 域
  • SpringMVC 的上下文是 Servlet 的 request 域