一、基础XML配置

1.WEB.xml配置如下

<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>Archetype Created Web Application</display-name><!--welcome pages--><welcome-file-list><welcome-file>index.jsp</welcome-file></welcome-file-list><!--  <listener><listener-class>org.apache.logging.log4j.web.Log4jServletContextListener</listener-class></listener><filter><filter-name>log4jServletFilter</filter-name><filter-class>org.apache.logging.log4j.web.Log4jServletFilter</filter-class></filter><filter-mapping><filter-name>log4jServletFilter</filter-name><url-pattern>/*</url-pattern><dispatcher>REQUEST</dispatcher><dispatcher>FORWARD</dispatcher><dispatcher>INCLUDE</dispatcher><dispatcher>ERROR</dispatcher></filter-mapping>--><!--配置springmvc DispatcherServlet--><servlet><servlet-name>springMVC</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><!--配置dispatcher.xml作为mvc的配置文件--><param-name>contextConfigLocation</param-name><param-value>/dispatcher-servlet.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><!--<servlet>--><!--<servlet-name>EmpServlet</servlet-name>--><!--<servlet-class>com.gx.filter.EmpServlet</servlet-class>--><!--</servlet>--><servlet-mapping><servlet-name>springMVC</servlet-name><url-pattern>/</url-pattern></servlet-mapping><!--把applicationContext.xml加入到配置文件中--><context-param><param-name>contextConfigLocation</param-name><param-value>/applicationContext.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><!--<listener>--><!--<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>--><!--</listener>--><!--    <context-param>-->
<!--        <param-name>log4jConfigLocation</param-name>-->
<!--        <param-value>classpath:log4j2.xml</param-value>-->
<!--    </context-param>--></web-app>

2.applicationContext.xml配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><context:component-scan base-package="com.tpw.service"/></beans>

3.dispatcher-servlet.xml配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!--此文件负责整个mvc中的配置--><!--启用spring的一些annotation --><context:annotation-config/><!-- 配置注解驱动 可以将request参数与绑定到controller参数上 --><mvc:annotation-driven><mvc:message-converters><bean class="org.springframework.http.converter.StringHttpMessageConverter"/><bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter"/></mvc:message-converters></mvc:annotation-driven><bean id="fastjson" class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter"><property name="supportedMediaTypes"><list><value>text/html;charset=UTF-8</value><value>application/json;charset=UTF-8</value></list></property></bean><!--静态资源映射--><!--本项目把静态资源放在了webapp的statics目录下,资源映射如下--><mvc:resources mapping="/css/**" location="/static/css/"/><mvc:resources mapping="/js/**" location="/static/js/"/><mvc:resources mapping="/image/**" location="/static/images/"/><mvc:default-servlet-handler/>  <!--这句要加上,要不然可能会访问不到静态资源,具体作用自行百度--><!-- 对模型视图名称的解析,即在模型视图名称添加前后缀(如果最后一个还是表示文件夹,则最后的斜杠不要漏了) 使用JSP--><!-- 默认的视图解析器 在上边的解析错误时使用 (默认使用html)- --><bean id="defaultViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/><property name="prefix" value="/WEB-INF/"/><!--设置JSP文件的目录位置--><property name="suffix" value=".jsp"/><property name="exposeContextBeansAsAttributes" value="true"/></bean><!-- 自动扫描装配 --><context:component-scan base-package="com.tpw.controller"/></beans>

二、tomcat容器引擎加载时首先加载web.xml所有配置的listener对象。\

1.我们配置的是

org.springframework.web.context.ContextLoaderListener,所有会加载此类contextInitialized方法,此方法会创建一个父类的applicationContext,加载applicationContext.xml文件中所有的扫描和配置的BEAN,并创建到容器工厂中。
 @Overridepublic void contextInitialized(ServletContextEvent event) {initWebApplicationContext(event.getServletContext());}

2.然后会调用org.springframework.web.context.ContextLoader.initWebApplicationContext,创建父类applicationContext,默认为org.springframework.web.context.support.XmlWebApplicationContext类环境。

public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) {throw new IllegalStateException("Cannot initialize context because there is already a root application context present - " +"check whether you have multiple ContextLoader* definitions in your web.xml!");}servletContext.log("Initializing Spring root WebApplicationContext");Log logger = LogFactory.getLog(ContextLoader.class);if (logger.isInfoEnabled()) {logger.info("Root WebApplicationContext: initialization started");}long startTime = System.currentTimeMillis();try {// Store context in local instance variable, to guarantee that// it is available on ServletContext shutdown.if (this.context == null) {this.context = createWebApplicationContext(servletContext);}if (this.context instanceof ConfigurableWebApplicationContext) {ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;if (!cwac.isActive()) {// The context has not yet been refreshed -> provide services such as// setting the parent context, setting the application context id, etcif (cwac.getParent() == null) {// The context instance was injected without an explicit parent ->// determine parent for root web application context, if any.ApplicationContext parent = loadParentContext(servletContext);cwac.setParent(parent);}configureAndRefreshWebApplicationContext(cwac, servletContext);}}servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);ClassLoader ccl = Thread.currentThread().getContextClassLoader();if (ccl == ContextLoader.class.getClassLoader()) {currentContext = this.context;}else if (ccl != null) {currentContextPerThread.put(ccl, this.context);}if (logger.isInfoEnabled()) {long elapsedTime = System.currentTimeMillis() - startTime;logger.info("Root WebApplicationContext initialized in " + elapsedTime + " ms");}return this.context;}catch (RuntimeException | Error ex) {logger.error("Context initialization failed", ex);servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);throw ex;}}

3.创建完applicationContext后,则会contextLoader.configureAndRefreshWebApplicationContext去配置configlocation的XML,以及ID名称,然后调用applicationContext.refresh去实例化工厂中的对象。

 protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {if (ObjectUtils.identityToString(wac).equals(wac.getId())) {// The application context id is still set to its original default value// -> assign a more useful id based on available informationString idParam = sc.getInitParameter(CONTEXT_ID_PARAM);if (idParam != null) {wac.setId(idParam);}else {// Generate default id...wac.setId(ConfigurableWebApplicationContext.APPLICATION_CONTEXT_ID_PREFIX +ObjectUtils.getDisplayString(sc.getContextPath()));}}wac.setServletContext(sc);String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);if (configLocationParam != null) {wac.setConfigLocation(configLocationParam);}// The wac environment's #initPropertySources will be called in any case when the context// is refreshed; do it eagerly here to ensure servlet property sources are in place for// use in any post-processing or initialization that occurs below prior to #refreshConfigurableEnvironment env = wac.getEnvironment();if (env instanceof ConfigurableWebEnvironment) {((ConfigurableWebEnvironment) env).initPropertySources(sc, null);}customizeContext(sc, wac);wac.refresh();}

4.application.refresh,则会根据applicationContext.xml中定义去扫描或者加载实例化BEAN,这个和spring ioc 原理一样.

三、org.springframework.web.servlet.DispatcherServlet初始化

1.DispatcherServlet静态代码执行,会将DispatcherServlet.properties配置的相应工厂SPI类配置读取出来到属性列表中。

包中的配置文件路径如下:

文件内容为:

# Default implementation classes for DispatcherServlet's strategy interfaces.
# Used as fallback when no matching beans are found in the DispatcherServlet context.
# Not meant to be customized by application developers.org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolverorg.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolverorg.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\org.springframework.web.servlet.function.support.RouterFunctionMappingorg.springframework.web.servlet.HandlerAdapter=org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,\org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,\org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter,\org.springframework.web.servlet.function.support.HandlerFunctionAdapterorg.springframework.web.servlet.HandlerExceptionResolver=org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolverorg.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslatororg.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolverorg.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager

2.会调用org.springframework.web.servlet.HttpServletBean.init 进行初始化。创建一个

BeanWrapper属性包装器,里面包装的是DispatcherServlet对象。会将web.xml中
param-name中的值设置到DispatcherServlet对象的属性包装器中,如contextConfigLocation属性设置为dispatcher-servlet.xml。

 public final void init() throws ServletException {// Set bean properties from init parameters.PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);if (!pvs.isEmpty()) {try {BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));initBeanWrapper(bw);bw.setPropertyValues(pvs, true);}catch (BeansException ex) {if (logger.isErrorEnabled()) {logger.error("Failed to set bean properties on servlet '" + getServletName() + "'", ex);}throw ex;}}

3.调用FrameworkServlet.initServletBean去创建子applicationContext.

 protected final void initServletBean() throws ServletException {getServletContext().log("Initializing Spring " + getClass().getSimpleName() + " '" + getServletName() + "'");if (logger.isInfoEnabled()) {logger.info("Initializing Servlet '" + getServletName() + "'");}long startTime = System.currentTimeMillis();try {this.webApplicationContext = initWebApplicationContext();initFrameworkServlet();}catch (ServletException | RuntimeException ex) {logger.error("Context initialization failed", ex);throw ex;}if (logger.isInfoEnabled()) {logger.info("Completed initialization in " + (System.currentTimeMillis() - startTime) + " ms");}}

调用栈

4.初始化applicationContext时首先会获取父的applicationContext,然后会创建的子CONTEXT,

wac = createWebApplicationContext(rootContext);
 org.springframework.web.servlet.FrameworkServlet
protected WebApplicationContext initWebApplicationContext() {WebApplicationContext rootContext =WebApplicationContextUtils.getWebApplicationContext(getServletContext());WebApplicationContext wac = null;if (this.webApplicationContext != null) {// A context instance was injected at construction time -> use itwac = this.webApplicationContext;if (wac == null) {// No context instance was injected at construction time -> see if one// has been registered in the servlet context. If one exists, it is assumed// that the parent context (if any) has already been set and that the// user has performed any initialization such as setting the context idwac = findWebApplicationContext();}if (wac == null) {// No context instance is defined for this servlet -> create a local onewac = createWebApplicationContext(rootContext);}if (!this.refreshEventReceived) {// Either the context is not a ConfigurableApplicationContext with refresh// support or the context injected at construction time had already been// refreshed -> trigger initial onRefresh manually here.synchronized (this.onRefreshMonitor) {onRefresh(wac);}}if (this.publishContext) {// Publish the context as a servlet context attribute.String attrName = getServletContextAttributeName();getServletContext().setAttribute(attrName, wac);}return wac;}

5.创建新的子applicationContext,并调用其refresh方法。设置根applicationContext为父。后面的refresh就是扫描dispatch-servlet.xml中的所有配置包,然后加载和实例化到容器工厂中。

 protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) {Class<?> contextClass = getContextClass();if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {throw new ApplicationContextException("Fatal initialization error in servlet with name '" + getServletName() +"': custom WebApplicationContext class [" + contextClass.getName() +"] is not of type ConfigurableWebApplicationContext");}ConfigurableWebApplicationContext wac =(ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);wac.setEnvironment(getEnvironment());wac.setParent(parent);String configLocation = getContextConfigLocation();if (configLocation != null) {wac.setConfigLocation(configLocation);}configureAndRefreshWebApplicationContext(wac);return wac;}

四、DispatchServlet的onfresh加载流程

1.在上述子applicationContext.refresh调用完毕时,会调用publishEvent(new ContextRefreshedEvent(this)),而DispatcherServlet的父类FrameworkServlet有一个内部类实现了applicationListener接口

 private class ContextRefreshListener implements ApplicationListener<ContextRefreshedEvent> {@Overridepublic void onApplicationEvent(ContextRefreshedEvent event) {FrameworkServlet.this.onApplicationEvent(event);}}

2.最终会触发到DispatchServlet.onRefresh接口

3.最终会初始化springmvc中的各种策略类。这种会创建对象,注入属性。

 protected void initStrategies(ApplicationContext context) {initMultipartResolver(context);initLocaleResolver(context);initThemeResolver(context);initHandlerMappings(context);initHandlerAdapters(context);initHandlerExceptionResolvers(context);initRequestToViewNameTranslator(context);initViewResolvers(context);initFlashMapManager(context);}

最主要的是初始handlerMapping,即根据URL找到对应的handlerAdapter.

4.初始化handlerAdapter

排序后

5.初始化异常解析器

排序 后

spring mvc 总体启动流程相关推荐

  1. 接收请求处理流程_从Tomcat入口了解Spring MVC的请求处理流程(2)问题答疑

    在上一篇 从Tomcat入口了解Spring MVC的请求处理流程 中主要介绍了spring mvc如何使用以及spring的DispatcherServlet加载细节以及URL映射配置,但是还是遗留 ...

  2. Spring MVC的处理流程详解

    本文来说下Spring MVC 的处理流程是怎样的 文章目录 Spring MVC概述 Spring MVC的处理流程 曾经的王者-Servlet 想要更进一步 Spring MVC-两级控制器方式 ...

  3. 面试官:Spring MVC的处理流程是怎样的?

    提起Spring MVC,你的第一印象是什么?一个简化Web开发的轻量级框架?实际上,现代开发过程中,开发流程与开发效率的不断提高,同时伴随着Restful与Json相结合的方式的兴起,使得多个设备跨 ...

  4. 请简述Spring MVC的执行流程

    需要面试文档可S我 今天我给大家介绍一下Spring MVC的详细执行流程.我把Spring MVC的执行流程划分为三个阶段,配置阶段.初始化阶段和运行阶段. 我整理了一张完整的执行流程图,需要高清图 ...

  5. Spring MVC中数据绑定流程和原理

    Spring MVC不支持表单日期字符串和日期类型之间的转换 Spring MVC数据绑定的流程(Spring MVC通过反射 机制对目标处理方法进行解析) 1.Spring MVC将ServletR ...

  6. Spring Boot的启动流程

    文章目录 Spring Boot Spring Boot概念 Spring Boot的启动流程 1. 构造SpringApplection的实例 2. 调用实例的run方法 Spring Boot启动 ...

  7. Spring MVC的请求处理流程

    Spring MVC的请求处理流程 DispatcherServlet的处理流程图 核心处理流程步骤 DispatcherServlet 的初始化过程 DispatcherServlet的处理流程图 ...

  8. Spring容器的启动流程

    (本文基于 Spring 的 5.1.6.RELEASE 版本) Spring的启动流程可以归纳为三个步骤: 1.初始化Spring容器,注册内置的BeanPostProcessor的BeanDefi ...

  9. Spring Boot项目启动流程

    概述 用过Spring Boot的应该都知道,在项目启动入口的主类main()方法里,一句简简单单的 SpringApplication.run( ... ); 便开启了项目的启动运行之路. 本文我们 ...

最新文章

  1. Android软键盘遮挡的四种解决方案
  2. DR模式 mysqlABB读写分离
  3. Python__面向对象思想
  4. 笔记-项目风险管理-风险应对
  5. [MATLAB调试笔记]Field plot (Ex,Ey,Ez,By,Bz)
  6. RouterOS V2.9.27 固定IP双电信分流教程(详)
  7. 阿里与网易考拉收购案谈崩?后者股价下跌5.01%
  8. 软件调试中的断点分类
  9. UVA 11423 - Cache Simulator (树状数组)
  10. 高通平台printk输出log到串口
  11. 线程池工厂方法newFixedThreadPool()和newCachedThreadPool()
  12. C# 编译器选项 /platform(指定输出平台)32位程序运行到x64平台的问题
  13. android gradle 在assembleRelease之前 or 之后执行自定义task
  14. 机械革命bios升级_旧笔记本光驱换SSD,升级内存,改造散热还能再战5年
  15. 应届生应聘软件开发岗位推荐书籍
  16. fastai 文本分类_使用Fastai v2和多标签文本分类器检查有毒评论
  17. VHDL矩阵键盘扫描数码管显示
  18. 微信小程序 | 小Demo_学生资讯 | 系统性学习 | 无知的我费曼笔记
  19. 全面的软件测试( 转)
  20. 深圳软件测试培训:软件测试的需求评审

热门文章

  1. SAP 取月度期初库存和月度期末库存(历史库存)
  2. sap中Excel的模版上传和下载
  3. SAP内存 和 ABAP内存 的简单介绍说明
  4. 从老赖们“维权”,看拍拍贷的底色
  5. mysql 5.7巡检脚本_mysql自动化巡检脚本生成html报告
  6. php中如何比较数组和字符串,PHP中数组和字符串的相互转换-PHP数组和字符串互相转换方法-吾爱编程网...
  7. mysql 回收空间_MySQL表的碎片整理和空间回收小结
  8. 启动定时器t0的工作指令是_看门狗的工作原理、应用和设计思路
  9. SQL语言之DQL语言学习(十一)分页查询
  10. 键盘和计算机之间的通信是单工通信,通信方式