摘要:本文主要记录springmvc的初始化流程,记录内容过于枯燥,不知道有没有人能看完。
目录
springmvc中最重要的两个组件
1.ContextLoaderListener
负责web容器启动时,初始化IOC容器,并将容器置入ServletContext中
2.DispatcherServlet
负责前端请求的分发,起到控制器的做用
springmvc中的最重要的配置文件
1.applicationContext-*.xml
1). 该类配置文件对应web.xml中【<context-param>】标签下的contextConfigLocation的配置文件路径,作用是将其xml中配置的java-bean加载到spring IOC容器中
2.springmvc-servlet.xml
1). 该类配置文件对应web.xml中的【<servlet>】标签下的contextConfigLocation的配置文件路径,作用是将其xml中配置的java-bean加载到springmvc IOC容器中
2). 此配置文件中一般配置:视图映射器、国际化、上传下载解析、controller层组件等
声明:这个时序图是我从一篇博文里面搬的。这边博文写的很好,我这里就直接引用地址了
一步一步手绘Spring MVC运行时序图_皮皮虾的博客-优快云博客_springmvc时序图
贴一段springmvc的web.xml代码
<!-- 监听器:启动Web容器时,自动装配ApplicationContext的配置信息,完成容器的初始化-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- springMVC的核心控制器 DispatcherServlet-->
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<!-- 指定springmvc的配置文件-->
<param-value>classpath*:springMVC-servlet.xml</param-value>
</init-param>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 指定spring初始化上下文时,需要解析并加载到容器的配置文件-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
classpath*:applicationContext*.xml
</param-value>
</context-param>
ContextLoaderListener
ContextLoaderListener类的代码
public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
/.../ 此处省略构造方法
@Override
public void contextInitialized(ServletContextEvent event) {
initWebApplicationContext(event.getServletContext()); // 此处是父类ContextLoader中的方法
}
/**
* Close the root web application context.
*/
@Override
public void contextDestroyed(ServletContextEvent event) {
closeWebApplicationContext(event.getServletContext());
ContextCleanupListener.cleanupAttributes(event.getServletContext());
}
}
ContextLoaderListener类的继承关系
说一下以上几个类和接口的作用
-
ContextLoader类
-
首先理解两个概念:全局上下文、根上下文
-
全局上下文:指的是整个web容器的上下文ServletContext,为spring IOC容器提供宿主环境
-
根上下文:WebApplicationContext,其实际的实现类是 XmlWebApplicationContext。这个就是spring的IoC容器
-
-
该类中的【initWebApplicationContext方法】来初始化spring IOC容器,并将其放入到全局上下文中
- 【createWebApplicationContext方法】创建WebApplicationContext根上下文
- 【configureAndRefreshWebApplicationContext方法】读取web.xml中配置的<context-param>中的spring*.xml配置文件,最后调用【onfresh】执行所有组件的创建
- 将WebApplicationContext放入ServletContext(Java Web的全局变量)中
-
-
ContextLoaderListener类
- 继承了ContextLoader类
- 实现了ServletContextListener接口的【contextInitialized方法】和【contextDestroyed方法】,且允许当前类配置在web.xml中可通过<listener>标签下来作为web容器启动的监听类
- web容器启动时,会调用该类中的【contextInitialized方法】
- 【contextInitialized方法】调用了其父类ContextLoader中的【initWebApplicationContext方法】来初始化spring IOC容器
-
ServletContextListener接口
- 继承了EventListener接口
- 声明了【contextInitialized方法】和【contextDestroyed方法】来供实现类实现
- 容器在启动和销毁时,会给实现了servletContextListener接口的监听器发出相应的通知
-
EventListener接口
- 空接口,里面什么都没有
- 官方定义:A tagging interface that all event listener interfaces must extend.
ContextLoaderListener初始化流程
- servletContextListener接口
- web容器在启动和销毁时,会向servletContextListener的实现类发送通知
- ContextLoaderListener类
- 实现了servletContextListener接口,固在web.xml中配置过后,会收到web容器请求的通知
- 继承了ContextLoader类,会调用其父类的方法来初始化spring IOC容器
- ContextLoader类
- 创建WebApplicationContext根上下文
- 读取web.xml中配置的<context-param>中的spring*.xml配置文件,最后调用【onfresh】执行所有组件的创建
- 将WebApplicationContext放入ServletContext(Java Web的全局上下文)中
DispatcherServlet
DispatcherServlet初始化流程
- contextLoaderListener监听器初始化完毕后,开始初始化web.xml中配置的Servlet,这里是DispatcherServlet
- DispathcerServlet存在多个父类,其继承关系的最高层是接口Servlet,该接口中存在【inti()方法】
- 在DispatcherServlet的继承关系中,其各种父类的作用:
- HttpServletBean类
- 把DispatchServlet封装成BeanWrapper。
- 给BeanWrapper设置属性。
- 调用空方法initServletBean,让子类FrameworkServlet接着干
- FrameworkServlet类
- 从ServletContext中获取根容器,也就是spring IOC容器
- 将springIOC容器设置为springmvc IOC容器的父容器
- 初始化springmvc IOC容器
- 调用DispatcherServlet的初始化方法onRefresh(wac)
- DispatcherServlet类
- 执行各组件的初始化
- 接收打参数context就是springmvc IOC容器
- HttpServletBean类
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
/**
* Initialize the strategy objects that this servlet uses.
* <p>May be overridden in subclasses in order to initialize further strategy objects.
*/
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context); // 文件上传
initLocaleResolver(context); // 本地解析
initThemeResolver(context); // 主题解析
initHandlerMappings(context); // 把request映射到具体的处理器上(负责找handler)
initHandlerAdapters(context); // 初始化真正调用controller的类
initHandlerExceptionResolvers(context); // 异常解析
initRequestToViewNameTranslator(context);
initViewResolvers(context); // 视图解析
initFlashMapManager(context); // 管理FlashMap,主要用于redirect
}
其他补充
- 如果没有配置spring IOC容器的话【即没有指定<context-param>标签下的xml配置文件】,spring mvc IOC容器会承载所有组件
- 如果配置了spring IOC容器,那么在整个web容器中就会存在父子双容器,一般情况下SpringMVC容器管理Controller组件,其它的交给Spring容器管理
- 如果没有配置springmvc IOC容器【即没有指定<servlet>标签下的xml配置文件】,那么web容器会去默认位置加载配置文件,从而初始化springmvc IOC容器
附带一个dispatcherServlet处理前端请求的时序图: