一、SpringMVC概述
1.什么是SpringMVC
- SpringMVC也叫Spring web mvc,是spring内置的一个MVC框架,在Spring3.0后发布。SpringMVC框架解决了web开发中常见的问题,例如参数接收、文件上传、表单验证等;
- SpringMVC使用简单,且与spring无缝集成(因为SpringMVC是Spring的四大模块之一Web中的一个子模块),支持RESTful风格的url请求,采用了松散耦合可插拔组件结构,比其他mvc框架更具有扩展性和灵活性
2.SpringMVC解决的问题
- 传统的web开发都是使用servlet,但是servlet在接收请求参数、数据共享、页面跳转等操作相对比较复杂;
- 比如我们经常需要先通过request接收参数、最后将数据添加到request作用域,然后进行转发或重定向等操作
- SpringMVC其实就是对servlet进行了深层次的封装,底层实现还是servlet,它免去了程序员的上述复杂操作,减少代码的冗余并简化开发流程
- 可以简单理解为SpringMVC其实就是替代框架中的servlet,对servlet进行了加强
3.SpringMVC的优势
- 基于MVC架构,功能分工明确,可以解决页面代码和后台代码的分离;
- 简单易用,是轻量级框架,jar包很小(因为Spring也是轻量的,作为Spring的一个子模块自然也是轻量的)。不依赖特定的接口和类就可以开发一个基于注解的SpringMVC项目;
- 作为Spring框架的一部分,能够使用Spring的IOC和AOP,便于整合MyBatis、Hibernate、JPA等其他框架
- SpringMVC的注解强大易用
二、SpringMVC工作流程的非源码级理解
SpringMVC的工作流程如果理解到位了也很容易记,不需要死记硬背。下面我会拆解每一个部分的功能,并简述SpringMVC框架的工作流程。把每一个模块都理解清楚后再串一遍印象就会比较深刻!
0.总体概述理解
- 如上图所示,这是SpringMVC的整体工作流程。我们可以看到有多个子模块,即:
DispatcherServlet:前端控制器/核心控制器/中央控制器,一般称为前端控制器;
HandlerMapping:处理器映射器
HandlerAdaptor:处理器适配器
Controller(Handler):处理器(后台控制器)
ViewResolver:视图解析器
View:视图
- 流程如上图的数字顺序标注一样,先有个简单的印象。从图中我们可以发现,DispatcherServlet和所有的其他模块都在打交道,也就是说DispatcherServlet其实就是大哥,是最核心的部分。
- 下面逐个拆解每一个模块进行解析,最后再进行整体的流程梳理
1.DispatcherServlet-前端控制器
- dispatcher这个单词是调度者的意思,因为SpringMVC其实就是对servlet进行封装,所以DispatcherServlet在这个框架中其实就扮演了最重要的调度者的作用。所有其他模块都跟它打交道,进而其他模块之间的直接联系就少了,从而降低了不同组件之间的耦合性;
- 所有的用户请求都会先发送给DispatcherServlet,由DispatcherServlet将用户请求转发给其他模块进行处理。大哥DispatcherServlet会先把请求转发给HandlerMapping(处理器映射器)进行处理;
- 在这一情境下,DispatcherServlet扮演了用户请求的入口控制器这一角色
- 在后面的环节中,DispatcherServlet就跟dispatcher单词的意思一样,主要起的是调度者的角色
- 需要注意的是,DispatcherServlet需要在web.xml中配置
2.HandlerMapping-处理器映射器
- HandlerMapping根据DispatcherServlet转发过来的用户请求,去拆解请求并找到对应的单个处理器(controller),和(单个/多个)拦截器,最后将这几个部分整合成一个处理器执行链(HandlerExecutionChina)返回给DispatcherServlet
- 找到处理器的意思是,根据请求判断是需要找哪个controller进行业务逻辑的处理,比如是需要登录逻辑的处理器,还是要条件查询逻辑的处理器?
- 找到拦截器的意思是,相当于是要给处理业务的逻辑加上的切面。在学习Spring的AOP时我们知道,我们通常会把一些非核心的业务逻辑抽离出来形成一个“切面”。在程序运行的时候拦截对应的业务方法,并根据切入点的位置、切入的时间等对业务逻辑进行代码增强
- 处理器执行链路可以这么理解,就是将这些切面、核心业务方法按执行顺序组成一条执行顺序链。我是这么理解的,因为写这篇文章的时候还没看过源码,希望大佬可以在评论区指正~
- 补充(如果只理解工作流程可以不看下面)
- 这里补充的内容和本文工作流程的学习没太大关系,但是和具体的实现有关系。处理器映射器的实现方式有多种,常用的就是使用@RequestMapping注解修饰控制器中的某个方法,并在注解参数中指定映射方法的url。然后再去springmvc的xml配置文件中加上一句<mvc:annotation-driven/>,即可开启根据url自动找到相应控制器方法的功能;
- 这一句话的作用相当于是先根据@Controller注解找到控制器的bean,再根据@RequestMapping注解中的url找到映射的方法
- 如果不写上面这一句代码,就需要自己通过配置Bean的方式来配置处理器映射器。HandlerMapping是一个接口,配置bean的时候配置它的实现类。它有多种实现类,比如根据bean的名字找到controller,或者是根据url找到controller的方法等
- 这里补充的内容和本文工作流程的学习没太大关系,但是和具体的实现有关系。处理器映射器的实现方式有多种,常用的就是使用@RequestMapping注解修饰控制器中的某个方法,并在注解参数中指定映射方法的url。然后再去springmvc的xml配置文件中加上一句<mvc:annotation-driven/>,即可开启根据url自动找到相应控制器方法的功能;
3.HandlerAdaptor-处理器适配器
- HandlerAdaptor主要是根据DispatcherServlet发过来的处理器执行链,去对相应的处理器进行执行,这用到了适配器模式的应用。操作完毕后,controller会返回一个ModelAndView对象给HandlerAdaptor,然后HandlerAdaptor再将结果原封不动返回给DispatcherServlet。
- 可以按下图的方式理解
- HandlerMapping返回的处理器执行链其实就是特定形状的插头,插电之后就可以实现某些功能,比如用户登录、列表查询等;而HandlerAdaptor就相当于一个插座,包含了各种不同形状的插口(这些不同的插口就是实现不同功能的controller)
- HandlerAdaptor处理器适配器从DispatcherServlet那里拿到这个插头之后,就会找到对应的插口,将插头插入后进行工作。这就相当于根据这个处理器执行链找到了相应的控制器(controller),然后根据执行链中的要求去完成操作(执行链是包含非核心逻辑和核心业务逻辑的)
-
关于java的适配器设计模式,见下面的链接
4.Controller(Handler)-后端控制器(处理器)
- controller主要和HandlerAdaptor(处理器适配器)进行交互,根据HandlerAdaptor的安排执行相应的方法,然后返回处理结果给HandlerAdaptor,也就是返回ModelAndView。
5.ViewResolver-视图解析器
- 视图解析器根据DispatcherServlet给的ModelAndView,去进行相应的处理。首先将ModelAndView对象中的逻辑视图名(比如index.jsp,逻辑视图名就是index,不包含后缀)解析成物理视图名(也就是具体的页面地址,比如jsp包下的index.jsp,物理视图名就是/jsp/index.jsp),然后再生成view视图对象返还给DispatcherServlet
- 简单说就是根据ModelAndView对象返回一个实际的页面地址和view对象给DispatcherServlet
6.View-视图
- 对DispatcherServlet传过来的view对象进行渲染,比如数据的填充、效果的展示等
- 比如页面要展示某个人的姓名,但是页面模板在姓名这里还没有具体的值,只有一个表达式。经过上述的处理后,传过来了一个叫小明的值,这个时候就把小明展示上去。这就是渲染
7.总结
- 如上图所示,虽然画的粗糙,但是通过上面不同模块的拆解,应该能够比较容易看懂了
- 后续会把实现springmvc的小例子也写个博客
- 图虽丑,看懂已足够~
- 有写的不好的地方欢迎批评指正,冲冲冲