Spring之MVC与Web环境

    Spring MVC是建立在IOC容器基础上的。

   DispachServlet和ContextLoaderListener提供在Web容器中对Spring的接口,这些接口与Web容器耦合是通过ServletContext来实现,ServletContext为Spring的IOC容器提供了一个宿主环境,Spring MVC建立起一个IOC容器体系。ContextLoaderListener定义为监听器,负责完成IOC容器在Web环境中的启动工作。 DispatcherServlet起着分发请求的作用,定义了对应的URL映射。

  <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容器的启动过程

     IOC容器的启动过程就是建立上下文的过程,与ServletContext相伴而生。

    spring使用默认的XmlWebApplicationContext作为IOC容器。

ContextLoaderListener

    ContextLoaderListener的作用就是启动启动IOC容器并将其载入到WEB容器,是整个sping web应用加载IOC容器的第一个地方。它实现了ServletContextListener接口,提供了与servlet生命周期结合的回调(contextInitialized, contextDestroyed)。ContextLoaderListener启动建立的上下文为根上下文,DispatcherServlet所创建的上下文的的父上下文即为此根上下文。具体的载入IOC容器的过程交由它的基类ContextLoader完成。

ContextLoader完成两个IOC容器的建立,一个是在Web容器中建立双亲IOC容器,另一个生成相应的WebApplicationContext并初始化。

DispatcherServlet

    DispatcherServlet会建立自己的上下文持有Spring MVC的Bean对象,在建立自己持有的这个IOC容器的时候,会从ServletContext中得到根上下文来作为DispatcherServlet持有的上下文的双亲上下文。最后把自己的上下文保存到ServletContext中。

    DispacherServlet的工作主要分为两个部分:一是初始化部分,由initServletBean()启动,通过initWebApplicationContext()最终调用DispatcherServlet的initStrategies()方法,对MVC模块的其他部分进行初始化(比如国际化、支持request映射的HandlerMapping等);另一个是对HTTP请求进行相应,作为Servlet,Web容器会调用Servlet的doGet()和doPost()方法,最终会调用DispatcherServlet的doService()方法,然后调用其封装的doDispacher()方法。

//MVC框架的初始化
protected void initStrategies(ApplicationContext context) {
    initMultipartResolver(context);
	initLocaleResolver(context);
	initThemeResolver(context);
	initHandlerMappings(context);
	initHandlerAdapters(context);
	initHandlerExceptionResolvers(context);
	initRequestToViewNameTranslator(context);
	initViewResolvers(context);
	initFlashMapManager(context);
}

MVC处理HTTP分发请求

在DispatcherServlet类的doService方法中,首先为Request请求设置了一些对应的属性实例,然后调用doDispatch方法去分发处理请求。以下是实际处理过程:

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中使用的特殊的Bean

DispatcherServlet默认使用WebApplicationContext作为上下文,因此我们来看一下该上下文中有哪些特殊的Bean:

1、Controller处理器/页面控制器,做的是MVC中的C的事情,但控制逻辑转移到前端控制器了,用于对请求进行处理;

2、HandlerMapping请求到处理器的映射,如果映射成功返回一个HandlerExecutionChain对象(包含一个Handler处理器(页面控制器)对象、多个HandlerInterceptor拦截器)对象;如BeanNameUrlHandlerMapping将URL与Bean名字映射,映射成功的Bean就是此处的处理器;

3、HandlerAdapterHandlerAdapter将会把处理器包装为适配器,从而支持多种类型的处理器,即适配器设计模式的应用,从而很容易支持很多类型的处理器;如SimpleControllerHandlerAdapter将对实现了Controller接口的Bean进行适配,并且掉处理器的handleRequest方法进行功能处理;

4、ViewResolverViewResolver将把逻辑视图名解析为具体的View,通过这种策略模式,很容易更换其他视图技术;如InternalResourceViewResolver将逻辑视图名映射为jsp视图;

5、LocalResover本地化解析,因为Spring支持国际化,因此LocalResover解析客户端的Locale信息从而方便进行国际化;

6、ThemeResovler主题解析,通过它来实现一个页面多套风格,即常见的类似于软件皮肤效果;

7、MultipartResolver文件上传解析,用于支持文件上传;

8HandlerExceptionResolver处理器异常解析,可以将异常映射到相应的统一错误界面,从而显示用户友好的界面(而不是给用户看到具体的错误信息);

9RequestToViewNameTranslator当处理器没有返回逻辑视图名等相关信息时,自动将请求URL映射为逻辑视图名;

10FlashMapManager用于管理FlashMap的策略接口,FlashMap用于存储一个请求的输出,当进入另一个请求时作为该请求的输入,通常用于重定向场景,后边会细述。

猜你喜欢

转载自my.oschina.net/u/1765168/blog/1797580