目录
前言
前面两章学习了SpringIOC、SpringAOP,今天学习Spring MVC。Spring MVC全名叫Spring Web MVC,是一种基于JAVA实现的MVC设计模型的请求驱动类型的轻量级Web框架。
一、什么是MVC设计模式?
MVC全名式Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,是一种用于设计创建Web应用程序表现层的模式。
- Model(模型):模型包含业务模型和数据模型,数据模型用于封装数据,业务模型用于处理业务。
- View(视图):通常指我们的jsp或者html。作用是展示数据,通常视图是依据模型数据创建的
- Controller(控制器):是应用程序中处理用户交互的部分,作用是处理程序逻辑。
二、 Spring MVC 工作流程
在讲Spring MVC流程前,我们以SpringBoot+SpringMVC+thymeleaf为例,看一下SpringBoot启动时做了哪些事情。
1.DispatcherServlet初始化
DispatcherServlet在启动时会调用initStrategies方法初始化,multipartResolver、localeResolver、themeResolver、handlerMapping、handlerAdapter、handlerExceptionResolver、viewNameTranslator、viewResolver、flashMapManager。其中我们主要关注的是handlerMapping、handlerAdapter、viewResolver。我们现在debug进去看一下启动时handlerMapping、handlerAdapter、viewResolver到底加载了哪些东西。
1.initHandlerMappings
如图所示handlerMappings是从ApplicationContext容器中获取HandlerMapping.class类型的Bean组成的。
继续执行发现handlerMappings主要包含7个HandlerMapping分别是requestMappingHandlerMapping、resourceHandlerMapping、welcomePageHandlerMapping、beanNameHandlerMapping、routerFunctionMapping、webEndpointServletHandlerMapping、controllerEndpointHandlerMapping。
2.initHandlerAdapters
如图所示handlerAdapters是从ApplicationContext容器中获取HandlerAdapter.class类型的Bean组成的。
继续执行发现handlerAdapters主要包含4个HandlerAdapter分别是RequestMappingHandlerAdapter、HandlerFunctionAdapter、HttpRequestHandlerAdapter、SimpleControllerHandlerAdapter。
3.initViewResolvers
如图所示viewResolvers是从ApplicationContext容器中获取ViewResolver.class类型的Bean组成的。
继续执行发现viewResolvers主要包含5个ViewResolver分别是BeanNameViewResolver、ViewResolverComposite、InternalResourceViewResolver、ContentNegotiatingViewResolver、ThymeleafViewResolver。
2. HandlerMapping初始化
这里我以RequestMappingHandlerMapping的源码来看,handlerMapping是如何初始化的。
我们根据继承关系可以看到RequestMappingHandlerMapping是实现了InitializingBean接口的。对于实现了 InitializingBean
接口的bean,Spring容器会特别调用其 afterPropertiesSet()
方法。
从afterPropertiesSet()
方法源码可知,RequestMappingHandlerMapping调用了父类的afterPropertiesSet()
方法;AbstractHandlerMethodMapping父类afterPropertiesSet()
方法又调用了自身的initHandlerMethods()方法,这个方法实际上会调用processCandidateBean()方法在这个方法中我们会看见我一直想看到的代码:
从中可以看到 RequestMappingHandlerMapping通过遍历容器中的bean查询到有@Controller和@RequestMapping注解的bean作为handler。然后调用detectHandlerMethods方法继续解析出类中的Method构造映射关系。
最后通过registerHandlerMethod方法和handler的映射关系注册到mappingRegistry中。需要注意的是注册过程是有加读写锁保证线程安全的。代码如下:
4.SpringMVC执行流程
- 用户发送请求到前端控制器,DispatcherServlet会调用doService()方法封装上下文信息,然后调用doDispatch(request, response)进行接下来的调用工作。
- DispatcherServlet接下来会调用getHandler方法查询handlerMapping。
- handlerMapping查询到handler后会将handler封装到HandlerExecutionChain对象中并返回给DispatcherServlet。
- DispatcherServlet收到回复后,根据handler去,DispatcherServlet中的handlerAdapters中获取handlerAdapter。
- 找到handlerAdapter后,调用handle方法执行handler
- Handler执行完成给处理器适配器返回ModelAndView
- 处理器适配器向前端控制器返回 ModelAndView,ModelAndView 是SpringMVC 框架的一个底层对 象,包括 Model 和 view
- 前端控制器请求视图解析器去进行视图解析,根据逻辑视图名来解析真正的视图。
- 视图解析器向前端控制器返回View
- 前端控制器进行视图渲染,就是将模型数据(在 ModelAndView对象中)填充到request 域
- 前端控制器向用户响应结果