vlambda博客
学习文章列表

手撸Spring系列5:Spring MVC(理论篇)

说在前头: 笔者本人为大三在读学生,书写文章的目的是为了对自己掌握的知识和技术进行一定的记录,同时乐于与大家一起分享,因本人资历尚浅,发布的文章难免存在一些错漏之处,还请阅读此文章的大牛们见谅与斧正。若在阅读时有任何的问题,也可通过评论提出,本人将根据自身能力对问题进行一定的解答。

手撸Spring系列是笔者本人首次尝试的、较为规范的系列博客,将会围绕Spring框架分为 IOC/DI 思想、 Spring MVC、 AOP 思想、 Spring JDBC 四个模块,并且每个模块都会分为 理论篇、 源码篇、 实战篇 三个篇章进行讲解(大约12篇文章左右的篇幅)。从原理出发,深入浅出,一步步接触Spring源码并手把手带领大家一起写一个 迷你版的Spring框架 ,促进大家进一步了解Spring的本质!

由于源码篇涉及到源码的阅读,可能有小伙伴没有成功构建好Spring源码的阅读环境,笔者强烈建议:想要真正了解Spring,一定要构建好源码的阅读环境再进行研究,具体构建过程可查看笔者此前的博客:《如何构建Spring5源码阅读环境》

前言

手撸Spring系列经过前面四篇的讲解,IOC/DI已经是告一段落了。接下来笔者将继续向各位读者朋友们讲述Spring另一大模块Spring MVC!!


Spring MVC 处理流程

Spring MVC 处理流程如下:

  1. 用户发送request请求到前端控制器DispatcherServlet

  2. DispatcherServlet根据处理器Handler获取处理器适配器HandlerAdapter执行HandlerAdapter处理一系列的操作,如:参数封装,数据格式转换,数据验证等操作。

  3. 适配器执行处理器,即执行Controller中的方法。

  4. 处理器完成业务逻辑后返回ModelAndView

  5. 适配器将处理器的处理结果返回给前端控制器DispatcherServlet

  6. ModelAndView中的view名称传给viewReslover

  7. viewReslover通过view名称返回具体的view

  8. ModelAndView中的model注入到view

  9. 将最终经过视图渲染的view页面响应给用户。




Spring MVC 九大组件

以下九大组件的介绍摘抄自书籍:《Spring 5 核心原理》——谭勇德(Tom)

1.HandlerMapping

HandlerMapping是用来查找Handler的,也就是查找处理器,具体的表现形式可以是类,也可以是方法。比如,标注了@RequestMapping的每个方法都可以看成一个Handler。Handler负责实际的请求处理,在请求到达后,HandlerMapping的作用便是找到请求相应的处理器HandlerInterceptor


2.HandlerAdapter

从名字上看,HandlerAdapter是一个适配器。因为Spring MVC 中Handler可以是任何形式的,只要是能够处理请求便可。但是把请求交给Servlet的时候,由于Servlet的方法结构都是doService(HttpServletRequest req, HttpServletResponse resp)形式的,要让固定的Servlet处理方法调用Handler来进行处理,这一步工作便是HandlerAdaptter要做的事。


3.HandlerExceptionResolver

从组件的名字上看,HandlerExceptionResolver是用来处理Handler产生的异常情况的组件。具体来说,此组件的作用事根据异常设置ModelAndView,之后交给渲染方法进行渲染,渲染方法会将ModelAndView渲染成页面。不过要注意,HandlerExceptionResolver只用于解析对请求做处理阶段产生的异常,渲染阶段的异常不归他管,这也是Spring MVC 组件设计的一大原则——分工明确、互不干涉


4.ViewResolver

ViewResolver即视图解析器,相信大家对这个组件应该很熟悉了。通常在Spring MVC 的配置文件中,都会配上一个实现类来进行视图解析。这个组件的主要作用是将String类型的视图名称和Locale解析为View类型的视图,只有一个resolveViewName()方法。从方法的定义可以看出,Controller层返回的String类型的视图名viewName最终会在这里被解析成为View。View是用来渲染页面的,也就是说,他会将程序返回的参数和数据填入模板中,生成HTML文件。ViewResolver在这个过程中主要做两件大事:ViewResolver会找到渲染所用的模板(第一件大事)和所用的技术(第二件大事,其实也即是找到视图的类型,如JSP)并填入参数。默认情况下,Spring MVC 会为我们自动配置一个InternalResourceViewResolver,是针对JSP类型视图的。


5.RequestToViewNameTranslator

RequestToViewNameTranslator组件的作用是从请求中获取ViewName。因为iewResolver根据ViewName查找View,但有的Handler处理完成之后,没有设置View,也没有设置ViewName,便要通过哦这个组件来从请求中查找ViewName


6.LocaleResolver

ViewResolver组件的resolveViewName()方法需要两个参数,一个是视图名,另一个就是Locale。参数Locale是从哪来的?这就是LocaleResolver组件要做的事。LocaleResolver用于从请求中解析出Locale,比如在中国Locale当然就是zh-CN,用来表示一个区域。这个组件也是i18n的基础。


7.ThemeResolver

从名字便可以看出,ThemeResolver组件是用来解析主题的。主题就是样式、图片及他们所形成的显示效果的集合。Spring MVC 中一套主题对应一个properties文件,里面存放着与当前主题相关的所有资源,如图片、CSS样式等。创建主题非常简单,只需要准备好资源,然后新建一个“主题名.properties”并将资源设置进去,放在classpath下,之后便可以在页面中使用了。Spring MVC 中与主题有关的类有ThemeResolverThemeSourceTheme。ThemeResolver负责从请求中解析出主题名,ThemeSource则给了根据主题名找到具体的主题,其抽象也是Theme,可以通过Theme来获取主题和具体的资源。


8.MultipartResolver

MultipartResolver是一个大家很熟悉的组件,用于处理上传请求,通过将普通的请求包装成MultipartHttpServletRequest来实现。MultipartHttpServletRequest可以通过getFile()方法直接获得文件。如果上传多个文件,还可以调用getFileMap()方法得到Map<FileName, File>这样的结构。MultipartResolver的作用就是封装普通的请求,使其拥有文件上传功能


9.FlashMapManager

说到FlashMapManager组件,得先说一下FlashMap

FlashMap用于重定向时得参数传递,比如在处理用户订单时,为了避免重复提交,可以处理完post请求后重定向到一个get请求,这个get请求可以用来显示订单详细之类的信息。这样做虽然可以避免用户重新提交订单的问题,但在这个页面要显示订单的信息,这些数据从哪里获取呢?因为重定向是没有传递参数这一功能的,如果不想把参数写进URL(其实也不推荐这么做,除了URL有长度限制,把参数都直接暴露也不安全),那么就可以通过FlashMap来传递。只需要在重定向之前将要传递的数据写入请求(可以通过ServletRequestAttributes.getReauest()方法获得)的属性OUTPUT_FLASH_MAP_ATTRIBUTE中,这样在重定向之后的Handler中Spring就会自动将其设置到Model中,在显示订单信息的页面上就可以直接从Model中获取数据。

FlashMapManager就是用来管理FlashMap