Spring MVC是创建在IOC容器基础上的。前端
DispachServlet和ContextLoaderListener提供在Web容器中对Spring的接口,这些接口与Web容器耦合是经过ServletContext来实现,ServletContext为Spring的IOC容器提供了一个宿主环境,Spring MVC创建起一个IOC容器体系。ContextLoaderListener定义为监听器,负责完成IOC容器在Web环境中的启动工做。 DispatcherServlet起着分发请求的做用,定义了对应的URL映射。java
<servlet> <servlet-name>SpringDispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>SpringDispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
IOC容器的启动过程就是创建上下文的过程,与ServletContext相伴而生。web
spring使用默认的XmlWebApplicationContext做为IOC容器。spring
ContextLoaderListener的做用就是启动启动IOC容器并将其载入到WEB容器,是整个sping web应用加载IOC容器的第一个地方。它实现了ServletContextListener接口,提供了与servlet生命周期结合的回调(contextInitialized, contextDestroyed)。ContextLoaderListener启动创建的上下文为根上下文,DispatcherServlet所建立的上下文的的父上下文即为此根上下文。具体的载入IOC容器的过程交由它的基类ContextLoader完成。设计模式
ContextLoader完成两个IOC容器的创建,一个是在Web容器中创建双亲IOC容器,另外一个生成相应的WebApplicationContext并初始化。app
DispatcherServlet会创建本身的上下文持有Spring MVC的Bean对象,在创建本身持有的这个IOC容器的时候,会从ServletContext中获得根上下文来做为DispatcherServlet持有的上下文的双亲上下文。最后把本身的上下文保存到ServletContext中。框架
、jsp
DispacherServlet的工做主要分为两个部分:一是初始化部分,由initServletBean()启动,经过initWebApplicationContext()最终调用DispatcherServlet的initStrategies()方法,对MVC模块的其余部分进行初始化(好比国际化、支持request映射的HandlerMapping等);另外一个是对HTTP请求进行相应,做为Servlet,Web容器会调用Servlet的doGet()和doPost()方法,最终会调用DispatcherServlet的doService()方法,而后调用其封装的doDispacher()方法。post
//MVC框架的初始化 protected void initStrategies(ApplicationContext context) { initMultipartResolver(context); initLocaleResolver(context); initThemeResolver(context); initHandlerMappings(context); initHandlerAdapters(context); initHandlerExceptionResolvers(context); initRequestToViewNameTranslator(context); initViewResolvers(context); initFlashMapManager(context); }
在DispatcherServlet类的doService方法中,首先为Request请求设置了一些对应的属性实例,而后调用doDispatch方法去分发处理请求。如下是实际处理过程:url
1.在doDispatch方法中,调用checkMultipart方法去判断该请求是不是Multipart请求(好比文件上传),若是是,则使用MultipartResolver实例将请求转换为Multipart请求。
2.调用getHandler方法去获取HandlerExecutionChain实例对象。在该方法中首先查找符合当前的HandlerMapping实例,而后调用HandlerMapping实例getHandler方法去获取HandlerExecutionChain实例,该实例包装了HandlerMapping实例对象,并在该实例中设置了相匹配的拦截器。
3.调用getHandlerAdapter方法,为当前HandlerMapping实例查找对应的HandlerAdapter适配器实例。
4.调用HandlerExecutionChain实例的applyPreHandler方法,去调用其拦截器的preHandler方法(前置拦截方法)执行。若是返回true,则继续日后处理,不然中止方法调用处理。(前置拦截方法执行调用)
5.调用HandlerAdapter适配器实例的handler方法去处理当前请求,并返回对应的ModelAndView对象。(调用目标对象的对应方法执行)
6.调用HandlerExecutionChain实例的applyPostHandler方法,去调用其拦截器的postHandler方法(后置拦截方法)执行。(后置拦截方法执行调用)
7.调用processDispatchResult方法去处理最后结果(ModelAndView或者异常),该方法调用render方法去渲染解析最后视图。在render方法中首先经过ViewResolver解析器去获取对应的视图名称的视图View对象,最后在调用对应View对象的render方法渲染处理视图,并响应对应结果给客户端。(调用对应View渲染视图)
DispatcherServlet默认使用WebApplicationContext做为上下文,所以咱们来看一下该上下文中有哪些特殊的Bean:
1、Controller:处理器/页面控制器,作的是MVC中的C的事情,但控制逻辑转移到前端控制器了,用于对请求进行处理;
2、HandlerMapping:请求处处理器的映射,若是映射成功返回一个HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象;如BeanNameUrlHandlerMapping将URL与Bean名字映射,映射成功的Bean就是此处的处理器;
3、HandlerAdapter:HandlerAdapter将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持不少类型的处理器;如SimpleControllerHandlerAdapter将对实现了Controller接口的Bean进行适配,而且掉处理器的handleRequest方法进行功能处理;
4、ViewResolver:ViewResolver将把逻辑视图名解析为具体的View,经过这种策略模式,很容易更换其余视图技术;如InternalResourceViewResolver将逻辑视图名映射为jsp视图;
5、LocalResover:本地化解析,由于Spring支持国际化,所以LocalResover解析客户端的Locale信息从而方便进行国际化;
6、ThemeResovler:主题解析,经过它来实现一个页面多套风格,即常见的相似于软件皮肤效果;
7、MultipartResolver:文件上传解析,用于支持文件上传;
8、HandlerExceptionResolver:处理器异常解析,能够将异常映射到相应的统一错误界面,从而显示用户友好的界面(而不是给用户看到具体的错误信息);
9、RequestToViewNameTranslator:当处理器没有返回逻辑视图名等相关信息时,自动将请求URL映射为逻辑视图名;
10、FlashMapManager:用于管理FlashMap的策略接口,FlashMap用于存储一个请求的输出,当进入另外一个请求时做为该请求的输入,一般用于重定向场景,后边会细述。