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的上下文。

 

转载于:https://www.cnblogs.com/whx7762/p/7762665.html

<think>嗯,用户想了解SpringMVC启动流程,我得仔细想想怎么组织这个回答。首先,SpringMVC是基于Servlet的,所以应该从Web容器启动开始讲起。然后,可能需要提到DispatcherServlet,这是前端控制器,负责请求的分发。不过,我得确认一下启动流程的具体步骤,不能遗漏关键点。 我记得SpringMVC启动和Spring容器有关,可能涉及到ContextLoaderListener,用来加载根应用上下文。然后是DispatcherServlet初始化自己的上下文,并将其作为子上下文连接到根上下文。这点很重要,需要分清楚父子容器的关系。 接下来,DispatcherServlet的初始化过程可能包括各个组件的加载,比如处理器映射、适配器、视图解析器等。这些组件是在什么时候初始化的呢?应该是在DispatcherServlet的init方法中,具体可能是在初始化WebApplicationContext的时候。 还有,配置文件的加载位置,比如默认的配置文件是放在WEB-INF下的,但用户可以通过配置修改。可能需要提到namespace和contextConfigLocation的参数设置。 然后,处理请求的流程虽然用户没问,但启动流程完成后,处理请求的大致步骤可以简单带过,帮助用户理解整个框架的工作机制。比如处理器映射找到对应的Controller,然后执行方法返回ModelAndView,视图解析等等。 要注意用户可能对专业术语不太熟悉,需要用比较易懂的中文来解释。比如解释根上下文和子上下文的关系,可能用父子容器的例子来说明,根容器负责Service、DAO等,而子容器负责Controller、视图解析器等。 还需要检查一下流程的每个步骤是否正确,比如监听器创建根上下文,DispatcherServlet创建自己的上下文,然后初始化组件。然后是否在Servlet 3.0之后有基于Java的配置方式,可能不需要web.xml,但用户可能还在用旧版本,所以需要涵盖两种方式? 不过用户的问题主要是启动流程,应该集中在容器启动时的步骤,而不是配置方式。可能需要分点说明,结构清晰,逐步推进。 总结一下,应该分为几个步骤: 1. Web容器启动,加载web.xml。 2. ContextLoaderListener创建根应用上下文(父容器)。 3. DispatcherServlet初始化,创建自己的上下文(子容器),并关联父容器。 4. DispatcherServlet初始化各个组件(处理器映射、适配器等)。 5. 完成启动,等待请求。 中间需要详细说明每个步骤里发生了什么,比如根上下文加载哪些配置,子上下文加载哪些配置,组件如何初始化,以及可能的配置文件位置和参数设置。 另外,需要强调SpringMVC启动流程中的关键组件,比如DispatcherServlet的作用,上下文的分层结构,以及组件初始化的顺序。 可能用户在使用过程中遇到过启动问题,比如配置错误导致上下文未正确加载,所以明确这些步骤可以帮助用户排查问题。同时,可以给出一个流程图或者结构图,但文本描述需要清晰。 最后,是否需要补充一些注意事项,比如配置文件的命名,默认位置,或者常见的配置错误?可能对用户有帮助,但根据用户的问题,可能不需要太深入,保持回答的结构和关键点即可。</think>SpringMVC启动流程可分为以下几个关键步骤,其核心围绕**Web容器初始化**和**DispatcherServlet初始化**展开: --- ### 一、Web容器启动阶段 1. **加载`web.xml`** - Web容器(如Tomcat)启动时读取`web.xml`,解析其中配置的`<listener>`和`<servlet>`。 - **关键组件**: - `ContextLoaderListener`:创建根应用上下文(父容器),默认加载`/WEB-INF/applicationContext.xml`。 - `DispatcherServlet`:前端控制器,每个实例会创建独立的子应用上下文(子容器),默认加载`/WEB-INF/[servlet-name]-servlet.xml`。 --- ### 二、根应用上下文初始化 2. **`ContextLoaderListener`初始化** - 通过`contextInitialized()`方法创建`WebApplicationContext`(父容器)。 - 默认加载配置文件可通过`<context-param>`自定义: ```xml <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-root.xml</param-value> </context-param> ``` --- ### 三、DispatcherServlet初始化 3. **子应用上下文创建** - `DispatcherServlet`在首次请求或容器启动时初始化。 - 创建自己的`WebApplicationContext`(子容器),并关联父容器(`ContextLoaderListener`创建的根上下文)。 - **父子容器关系**: - 父容器:管理Service、DAO等通用Bean。 - 子容器:管理Controller、视图解析器等Web层Bean。 4. **初始化策略组件** - `DispatcherServlet`通过`onRefresh()`方法初始化九大组件: ```java initMultipartResolver(); // 文件上传解析器 initLocaleResolver(); // 本地化解析 initThemeResolver(); // 主题解析 initHandlerMappings(); // 处理器映射(如@RequestMapping映射) initHandlerAdapters(); // 处理器适配器(如处理@Controller) initHandlerExceptionResolvers(); // 异常解析器 initRequestToViewNameTranslator(); initViewResolvers(); // 视图解析器(如InternalResourceViewResolver) initFlashMapManager(); ``` --- ### 四、请求处理流程(启动完成后的运行时) 1. **请求到达`DispatcherServlet`** 2. 通过`HandlerMapping`找到对应的`Controller`方法。 3. `HandlerAdapter`执行方法并返回`ModelAndView`。 4. `ViewResolver`解析视图,渲染响应。 --- ### 五、流程图示例 ```text Web容器启动 → 加载web.xml → ContextLoaderListener创建根上下文(父容器) → DispatcherServlet初始化子上下文(子容器) → DispatcherServlet加载九大组件 → 启动完成,等待请求 ``` --- ### 六、关键配置项 - **根上下文配置**:通过`contextConfigLocation`指定。 - **子上下文配置**:通过`DispatcherServlet`的`namespace`或`contextConfigLocation`参数指定。 --- 通过以上步骤,SpringMVC完成了父子容器的分层管理及核心组件的装配,最终形成一个完整的MVC请求处理体系。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值