zoukankan      html  css  js  c++  java
  • SpringMVC的启动过程

    前言

    下面是一个SpringMVC应用的配置文件,需要注意两个地方,一个是ContextLoaderListener,一个是dispatcherServlet。web容器正是通过这两个配置才和spring管理起来。ContextLoaderListener与web容器的ServletContext关联,为Spring的IOC容器提供了一个宿主环境。在建立起IOC容器体系之后,把DispatcherServlet作为SpringMVC处理web请求的转发器建立起来,完成响应http请求的准备。

    SpringMVC启动过程大致分为两个阶段:

    第一阶段.ContextLoaderListener初始化,实例化IOC容器,并将此容器注册到ServletContext中。

    第二阶段DispatcherServlet初始化,建立自己的上下文,也注册到ServletContext中。

    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
          http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
          version="3.1">
    
        <display-name>ota</display-name>
        <description>ota web application</description>
        
        <!-- 系统组件加载顺序:context-param -> listener -> filter -> servlet -->
         <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:/applicationContext.xml</param-value>
        </context-param>
        
        <listener>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
        
        <!-- GZip -->
        <filter>
            <filter-name>gzipFilter</filter-name>
            <filter-class>com.travelsky.ibeplus.compress.Compress2WayFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>gzipFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
        
        <!--  Servlet that dispatches request to registered handlers (Controller implementations).  -->
        <servlet>
            <servlet-name>ota</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:spring/mvc-core-config.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
    
        <!-- 需要定义在对应的servlet之后 -->
        <servlet-mapping>
            <servlet-name>ota</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
         
    </web-app>

    1、Spring IOC容器的启动

    Spring IOC容器的启动在我博客中这一篇博文“Spring是怎样启动的” 有详细介绍,这里再简单概述下。

    ContextLoaderListener实现ServletContextListener,这个接口里面的方法会结合web容器的生命周期被调用。因为ServletContextListener是ServletContext的监听者,如果ServletContext发生变化,会触发相应的事件,而监听者一直对这些事件进行监听,如果接受到了监听的事件,就会作于相应处理。例如在服务器启动,ServletContext被创建的时候,ServletContextListener的contextInitialized()方法被调用,从而拉开了初始化Spring IOC容器的序幕

    2、DispatcherServlet的启动  (HttpServletBean *  FrameworkServlet * DispatcherServlet)

    DispatchServlet本质上是一个Servlet,web容器启动的时候,servlet也会初始化,其init方法被调用,开启初始化之旅。

    DispatchServlet会建立自己的上下文来持有Spring MVC特殊的bean对象,在建立这个自己持有的Ioc容器的时候,会从ServletContext中得到根上下文作为DispatchServlet上下文的parent上下文。有了这个根上下文,再对自己持有的上下文进行初始化,最后把自己持有的这个上下文保存到ServletContext中,供以后检索和使用。

    下面来详细解释下:

    • DispatchServlet名如其义,它的本质上是一个Servlet,子类不断的对HttpServlet父类进行方法扩展
    • HttpServlet有两大核心方法:init()和service()方法。HttpServletBean重写了init()方法,在这部分,我们可以看到其实现思路:公共的部分统一来实现,变化的部分统一来抽象,交给其子类来实现,故用了abstract class来修饰类名。此外,HttpServletBean提供了一个HttpServlet的抽象实现,使的Servlet不再关心init-param部分的赋值,让servlet更关注于自身Bean初始化的实现
    • FrameworkServlet提供了整合web javabean和spring application context的整合方案。在源码中可以看到通过执行initWebApplicationContext()方法和initFrameworkServlet()方法实现
    • DispatchServlet是HTTP请求的中央调度处理器,它将web请求转发给controller层处理,它提供了敏捷的映射和异常处理机制,DispatchServlet转发请求的核心代码在doService()方法中实现

    2.1 HttpServletBean

     

     上图是抽象类HttpServletBean的实现,我们知道HttpServlet有两大核心方法:init()和service()方法。HttpServletBean重写了init()方法,在这部分,我们可以看到其实现思路:公共的部分统一来实现,变化的部分统一来抽象,交给其子类来实现,故用了abstract class来修饰类名。此外,HttpServletBean提供了一个HttpServlet的抽象实现,使的Servlet不再关心init-param部分的赋值,让servlet更关注于自身Bean初始化的实现。

    2.2 FrameworkServlet

     在HttpServletBean中有一方法initServletBean()需要子类去实现,因此 FrameworkServlet需要实现initServletBean()方法

    2.3 DispatcherServlet

    在FrameworkServlet中有一方法onRefresh()需要子类去实现,因此DispatcherServlet需要去实现onRefresh()方法。

    另外一些MVC的特性初始化时在initStrategies()中实现的,包括支持国际化的LocalResolver、支持Request映射的HandlerMappings,以及视图生成的ViewResolver等等。

    比如初始化HandlerMappings,在SpringMVC中,HandlerMappings的作用是为Http请求找到对应的Controller控制器,来进一步处理请求。

     注意:

    在web.xml配置文件中,DispatcherServlet中有一配置<load-on-startup>1</load-on-startup>,表示在容器启动的时候就加载该servlet。

    当<load-on-startup>值为0或者大于0时,表示容器在应用启动时就加载这个servlet(实例化并调用其init()方法)。

    当是一个负数时或者没有指定时,则表示第一次请求该servlet才加载

    正数的值越小,启动该servlet的优先级越高。

    3. DispatcherServlet类和ContextLoaderListener类的关系图:

    小结:首先,用ContextLoaderListener初始化上下文,接着使用DispatchServlet来初始化WebMVC的上下文。

  • 相关阅读:
    一个、说到所有的扩展指标
    时序图、流程图
    流程图总结
    UML活动图与流程图的区别
    类图与对象图
    app的描述-软件的描述
    UML的目标
    软件建模的用途
    Android中如何使用Intent在Activity之间传递对象[使用Serializable或者Parcelable]
    Serializable 和 Parcelable 区别
  • 原文地址:https://www.cnblogs.com/whx7762/p/7762665.html
Copyright © 2011-2022 走看看