一、SpringMVC 执行原理
SpringMVC 的设计是围绕 DispatcherServlet 展开的,DispatcherServlet 负责将请求派发到特定的 Controller,Controller 返回的结果经过 ViewReolver 解析得到对应的视图 或者 视图对象等,体现出 MVC 模式
- 用户对服务器发送请求,请求被 前端控制器 DispatcherSevlet 所捕获。
- DispatcherSevlet 会对请求的 URL 进行解析,得到请求资源标识符 (URI) 。然后根据请求的 URI,调用 HandlerMapping (映射处理器) 获得该 Handler 配置的所有相关对象 (包括 Handler 对象 以及 Handler 对象对应的拦截器)。 最后返回 HandlerExecutionChain 对象。
- DispatcherServlet 根据获得的 Handler,选择一个合适的 HandlerAdapter (处理适配器)。执行相对应的 Controller (如果完成了 HandlerAdapter 后,此后将执行拦截器的 preHandler(..) 方法。
提取 Raequest 中的模型数据,填充 Handler 入参,开始执行 Handler(Controller)。在填充过程中,根据配置,Spring 会为我们做一些额外的工作
- HttpMessageConveter:
- 将请求消息 (如 json,xml 等数据)转换为一个对象 ,将对象转换为指定的响应消息。
- 数据转换:对请求消息进行数据转换 (如 String 转换为 Integer,Double 等)
- 数据格式化:对请求消息进行数据格式化。如将字符串转换成格式化数字或格式化日期等。
- 数据验证:验证数据的有效性(长度、格式等),验证结果存储到 BindingResult 或 Error 中
- HttpMessageConveter:
Handler 执行完成后,向 DispatcherServlet 返回一个 ModelAbdView 对象
- 根据返回的 ModelAndView,选择一个合适的 ViewResolver(视图解析器),必须已经注册到 Spring 容器中 ViewResolver 返回给 DispatcherServlet
- ViewResolver 结合 Model 和 View,来渲染视图。
- 将渲染结果返回给前端。
二、核心控制器 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 处理器有两类:
- BeanNameUrlHandlerMapping
- 实现 Controller 接口的控制器会使用该处理器
- 实现 httpRequestHandler 接口的控制器也会使用该处理器
- RequestMappingHandlerMapping
- 使用注解式的控制器会使用该处理器
- HandlerAdapter
HandlerAdapter 将会把 处理器 包装成 适配器, 从而支持多种类型的的处理器,即 适配器设计模式 的应用,从而很容易支持多种类型的处理器,如 SimpleControllerHandlerAdapter 将对实现了 Controller 接口的 Bean 进行适配,并处理掉处理器的 handleRequest 方法进行功能处理。
补充:
- 实现了 Controller 接口的控制器 会使用 SimpleControllerHandlerAdapter 进行适配
- 实现了 HttpRequestHandler 接口控制器,会使用 HttpRequestHandlerAdapter 进行适配
- 使用了注解方式的控制器,会使用 requestMappingHandlerAdapter 进行适配
- Controller —> HandlerMapping —> HandlerAdapter 图解
- 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 域