Spring3.1.0实现原理分析(十二).MVC核心类DispatcherServlet初始化过程

来源:互联网 发布:终结者4知乎 编辑:程序博客网 时间:2024/06/18 15:00
大家好,今天我们分析下DispatcherServlet的初始化过程,下面的配置大家一定不陌生吧,只要使用spring mvc框架大多会在web.xml文件中加入这么一段配置,可见这个类是spring mvc的核心类,就是由它负责处理request请求的,在DispatcherServlet的初始化过程中也会创建web容器,结合上篇博客的内容,这里创建的web容器就是子web容器,而它的父web容器就是在ContextLoaderListener中创建的根web容器。
<servlet><servlet-name>petclinic</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class></servlet>


先上一张类结构图,DispatcherServlet还有两个超类,它们各自负责实现初始化过程中某部分功能。

     


我们来分析下这个图。

        最上面的抽象类HttpServletBean派生自HttpServlet,说明它是一个servlet类,另外它还实现了spring的EnvironmentAware接口,说明它具备获取一个环境对象的能力。HttpServletBean本身有个成员变量environment,它的默认值是StandardServletEnvironment对象,既然都已拥有了环境对象为什么还要实现这个接口呢?目的应该是让用户有扩展的机会,比如用户可以编写一个StandardServletEnvironment的派生类,然后把这个类赋值HttpServletBean。对于spring环境对象没概念的朋友,可以看下这篇博客《Spring3.1.0实现原理分析(三).配置数据》。

HttpServletBean重写了GenericServlet的init()方法,这个方法是servlet初始化的入口方法。HttpServletBean在这个方法中负责把用户配置的servlet参数“init-param”赋值给本类成员变量,用户可以在web.xml为DispatcherServlet配置哪些初始化参数呢,大致有如下,

  • String contextId: web容器Id,如果用户未配置spring自动生成。
  • String namespace: 命名空间,如果未配置就是servletname。
  • String contextConfigLocation: servlet配置文件地址,如果用户未配置默认是/WEB-INF/+namespace+.xml
  • boolean publishEvents :是否在每次请求结束后发布一个ServletRequestHandledEvent对象,默认true,如果修改成false据说能提升性能。
  • boolean dispatchOptionsRequest :是否处理OPTIONS请求,默认false。
  • boolean dispatchTraceRequest:是否处理TRACE请求,默认false。
  • String contextInitializerClasses:配置容器初始化器类型,多个用逗号分隔,用户可以通过编写容器初始化器对web容器执行扩展操作。

       

      接着来看FrameworkServlet类,HttpServletBean把用户配置的初始化参数赋值给成员变量后,会调用一个空方法initServletBean(),然后派生类FrameworkServlet就通过重写该方法继续初始化工作。FrameworkServlet类主要负责创建子web容器,会把在ContextLoaderListener中创建的根web容器作为父容器赋值给子web容器,然后把子web容器置入servletContext的属性集,key是“org.springframework.web.servlet.FrameworkServlet.CONTEXT.”+servletName。web容器会通过重写传统容器的postProcessBeanFactory(beanFactory)方法,在创建过程中增加些额外处理,这个在上篇博客中也有论述
       

       最后是DispatcherServlet类,在FrameworkServlet把子web容器置入SC之前,会调用本类一个空方法onRefresh(web容器),DispatcherServlet通过重写这个方法继续初始化操作。DispatcherServlet主要职责是“初始化策略对象”。什么是策略对象呢?就是一组spring默认的,用来实现MVC框架各种功能的实现类。比如像文件上传、URL映射、异常处理、视图解析等功能,针对不同的功能spring有专门的实现类,正如Spring官网对自己MVC框架的评价“职责分离”。这些默认的策略对象有部分被配置在DispatcherServlet.properties文件中,这个文件的全路径是“org\springframework\web\servlet\DispatcherServlet.properties”。那么具体会在DispatcherServlet类中初始化哪些策略对象呢,有如下。

  1. 文件上传解析器 : 这个用户必须在spring servlet配置文件中显示配置,否则为null。
  2. 本地化对象解析器 : 默认值是AcceptHeaderLocaleResolver。
  3. 主题解析器 :默认值是FixedThemeResolver。
  4. URL映射解析器:有RequestMappingHandlerMapping,BeanNameUrlHandlerMapping。这两个不是配置在DispatcherServlet.properties文件中,而是用户如果配置了<mvc:annotation-driven />,spring自动注册的。
  5. 处理器适配器:有RequestMappingHandlerAdapter,HttpRequestHandlerAdapter,SimpleControllerHandlerAdapter,AnnotationMethodHandlerAdapter。这几个也是spring自动注册。
  6. 异常解析器:有ExceptionHandlerExceptionResolver,ResponseStatusExceptionResolver,DefaultHandlerExceptionResolver,SimpleMappingExceptionResolver。这几个也是spring自动注册。
  7. 视图名称转换器:默认值是DefaultRequestToViewNameTranslator。
  8. 视图解析器:有ContentNegotiatingViewResolver,BeanNameViewResolver,InternalResourceViewResolver,也是spring自动注册。
  9. 闪属性管理器:默认值是DefaultFlashMapManager。
上述各个对象其实就是spring mvc框架的核心类,我会在后续博客中逐一分析。最后强调下,在ContextLoaderListener中创建的web容器叫根web容器,而DispatcherServlet初始化过程中创建的web容器,是其子容器,可以在web.xml文件中配置多个DispatcherServlet,那么就会有多个子web容器,但是根web容器只有一个。

      

阅读全文
0 0