解析 SpringMVC 父子容器及九大内置组件加载过程

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 解析 SpringMVC 父子容器及九大内置组件加载过程

在解析整个 mvc 父子容器加载过程时,先了解一些基本的流程和知识,Spring MVC 启动需要 Tomcat 容器来进行嵌入,启动 Tomcat 容器->加载项目的 web.xml 文件->启动 Spring 容器->启动 Spring MVC 容器.

Tomcat 安装启动及 idea 如何配置可以搜索网上其他文章进行构建.

web.xml 入口

<?xml version="1.0" encoding="UTF-8"?>
<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_4_0.xsd"
         version="4.0">
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-config.xml</param-value>
    </context-param>
    <servlet>
        <servlet-name>mvc-test</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <!--SpringMVC 配置文件 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:applicationContext.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
        <async-supported>true</async-supported>
    </servlet>
    <servlet-mapping>
        <servlet-name>mvc-test</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
</web-app>

<context-param> 标签 contextConfigLocation 参数 配置的是 Spring 父容器的配置文件,<servlet> 标签下 contextConfigLocation 参数配置的是 Spring MVC 子容器的配置文件,load-on-startup 配置为 1 或者 0 代表的是启动 Tomcat 容器后要进行 Servlet 加载及初始化,配置为 -1 代表只有请求 servlet 时才会被加载及初始化

父容器

ContextLoaderListener 上下文加载监听器这个类就至关重要了,tomcat 启动以后会调用该类下的初始化方法 contextInitialized,用于启动父容器,流程图如下所示:

contextInitialized 方法会调用其父类 ContextLoader#initWebApplicationContext 方法,其下有静态代码块用于加载 spring-web 模块下的 ContextLoader.properties 文件.

org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext
  • 首先当前的 ServletContext 中是否包含 .ROOT 字符,如果包含则抛出异常,提示 web.xml 不能多次定义 ContextLoader
  • 创建上下文对象,实例化 XmlWebApplicationContext 类型,其父类为 AbstractRefreshableWebApplicationContext,在其构造方法内会设置具体的展示名称:setDisplayName(“Root WebApplicationContext”),标识其为 ROOT 父容器
  • 最后,完成上下文的属性设置工作以及调用 refresh 方法完成 xml 文件解析、bean 实例化/初始化工作
  • 解析当前 web.xml 文件中是否配置了 contextId 初始化参数,如果有就设置 id 为 contextId 参数值,否则就拼接当前类名+上下文路径作为 id 名称.
  • 设置 ServletContext,类型为 ApplicationContextFacade,其类型为 tomcat catelina 包下的
  • 设置环境对象的属性资源变量值:servletContextInitParams、servletConfigInitParams 以及 SystemProperties、SystemEnv.
    到此,spring 父容器已经加载完毕.

子容器

父容器加载完毕,接下来还需要将 spring mvc 子容器进行加载工作,相信学习过 servlet 知识的同学都知道,init->service->destroy 这三个方法是执行或调用 servlet 所必须经过的历程,所以首先我们要先找到核心的方法 init,spring mvc 核心处理类:DispatcherServlet,观察其源码发现其并没有重写 init 方法,那么就可以观察它的父类,总会有实现 init 方法的父类.

通过前面给出的 web.xml 文件,servlet 标签下包裹的类型为:org.springframework.web.servlet.DispatcherServlet,其下还配置了 init-param 指向的 Spring MVC 子容器需要进行解析的 xml 配置文件,Spring MVC 子容器详细的加载流程图如下:

  1. 因为 DispatcherServlet 类没有对应的 init 方法,所以一直找它的父类,FrameworkServlet 内也没有 init 方法,所以还是找它的父类 HttpServletBean:在它下面有调用 init 方法进行容器的加载工作.
  2. Spring MVC 子容器创建时和父容器过程是一摸一样的,只是在属性上的设置做了一些区分的动作,例如:
    添加监听器 SourceFilteringListener 到 wac 中,实际是通过 ContextRefreshListener 去监听对应的事件:ContextRefreshedEvent,当监听器接收到消息之后会调用 onApplicationEvent 方法,执行 onRefresh 方法,将 refreshEventReceived 标志设置为 true,表示已经 refresh 过,该事件的处理主要的目的就是为了完成 Spring MVC 九大内置组件的加载工作.
    当执行 AbstractApplicationContext#refresh 方法内的 finshRefresh 时,会发布上下文的刷新事件,然后 FremeworkServlet.ContextRefreshListener 监听器就会接收到事件对其进行处理工作.
  3. 除了在执行 refresh 方法时会触发事件的发布,在 Spring MVC 子容器加载完以后,会判断 refreshEventReceived 标志是否为 false:如果是,代表还没进行刷新工作,会手动调用 DispatcherServlet#onRefresh 方法执行.

对以上内容进行总结:Spring MVC 启动是依赖于 Tomcat 服务的,所以整体的加载流程(启动 Tomcat->加载 web.xml 文件->Spring 容器->Spring MVC 容器)完成以后,后面就只需要对其进行调用了.

九大内置组件对象

加载 DispatcherServlet 类时,会执行 static 静态代码块,DispatcherServlet.properties 加载这个文件的属性源,在 spring-web-mvc 模块中,resource 目录下的 resources/org/springframework/web/servlet/DispatcherServlet.properties,其文件内容如下:

org.springframework.web.servlet.LocaleResolver=org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
org.springframework.web.servlet.ThemeResolver=org.springframework.web.servlet.theme.FixedThemeResolver
org.springframework.web.servlet.HandlerMapping=org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,\
  org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping,\
  org.springframework.web.servlet.function.support.RouterFunctionMapping
org.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.HandlerFunctionAdapter
org.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.DefaultHandlerExceptionResolver
org.springframework.web.servlet.RequestToViewNameTranslator=org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator
org.springframework.web.servlet.ViewResolver=org.springframework.web.servlet.view.InternalResourceViewResolver
org.springframework.web.servlet.FlashMapManager=org.springframework.web.servlet.support.SessionFlashMapManager

以下是 initStrageties 初始化策略器方法的执行流程图,如下:

  1. 初始化 MultipartResolver:主要用来处理文件上传,如果定义过当前类型的 bean 对象,那么直接获取,如果没有的话,可以为 null,一般使用的类:CommonsMultipartResolver
  2. 初始化 LocaleResolver:主要用来处理国际化配置,基于URL参数的配置(AcceptHeaderLocaleResolver),基于session的配置(SessionLocaleResolver),基于cookie的配置(CookieLocaleResolver)
  3. 初始化 ThemeResolver:主要用来设置主题 Theme,一般过节的时候,如:清明节或国家重要的节日,都是会切换主题背景的.
  4. 初始化 HandlerMapping 映射器:用来将对应的 request 跟 controller 进行对应
  5. 初始化 HandlerAdapter 处理适配器:主要包含 Http 请求处理器适配器,简单控制器处理器适配器,注解方法处理器适配器
  6. 初始化 HandlerExceptionResolver:基于 HandlerExceptionResolver 接口的异常处理
  7. 初始化 RequestToViewNameTranslator:当 controller 处理器方没有返回一个 View 对象或逻辑视图名称,并且在该方法中没有直接往 response 输出流里面写数据的时候,spring 将会采用约定好的方式提供一个逻辑视图名称
  8. 初始化 ViewResolver:将 ModelAndView 选择合适的视图进行渲染的处理器
  9. 初始化 FlashMapManager:提供请求存储属性,可供其他请求使用

总结

以上就是父子容器以及 Spring MVC 九大内置组件的加载过程详细解析.

如果觉得博文不错,关注我 vnjohn,后续会有更多实战、源码、架构干货分享!

大家的「关注❤️ + 点赞👍 + 收藏⭐」就是我创作的最大动力!谢谢大家的支持,我们下文见!

目录
相关文章
|
10天前
|
前端开发 JavaScript
React 步骤条组件 Stepper 深入解析与常见问题
步骤条组件是构建多步骤表单或流程时的有力工具,帮助用户了解进度并导航。本文介绍了在React中实现简单步骤条的方法,包括基本结构、状态管理、样式处理及常见问题解决策略,如状态管理库的使用、自定义Hook的提取和CSS Modules的应用,以确保组件的健壮性和可维护性。
48 17
|
2月前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
228 2
|
16天前
|
前端开发 UED
React 文本区域组件 Textarea:深入解析与优化
本文介绍了 React 中 Textarea 组件的基础用法、常见问题及优化方法,包括状态绑定、初始值设置、样式自定义、性能优化和跨浏览器兼容性处理,并提供了代码案例。
42 8
|
24天前
|
安全 持续交付 Docker
深入理解并实践容器化技术——Docker 深度解析
深入理解并实践容器化技术——Docker 深度解析
43 2
|
29天前
|
存储 安全 Java
Java多线程编程中的并发容器:深入解析与实战应用####
在本文中,我们将探讨Java多线程编程中的一个核心话题——并发容器。不同于传统单一线程环境下的数据结构,并发容器专为多线程场景设计,确保数据访问的线程安全性和高效性。我们将从基础概念出发,逐步深入到`java.util.concurrent`包下的核心并发容器实现,如`ConcurrentHashMap`、`CopyOnWriteArrayList`以及`BlockingQueue`等,通过实例代码演示其使用方法,并分析它们背后的设计原理与适用场景。无论你是Java并发编程的初学者还是希望深化理解的开发者,本文都将为你提供有价值的见解与实践指导。 --- ####
|
1月前
|
运维 持续交付 虚拟化
深入解析Docker容器化技术的核心原理
深入解析Docker容器化技术的核心原理
45 1
|
1月前
|
前端开发 JavaScript 开发者
揭秘前端高手的秘密武器:深度解析递归组件与动态组件的奥妙,让你代码效率翻倍!
【10月更文挑战第23天】在Web开发中,组件化已成为主流。本文深入探讨了递归组件与动态组件的概念、应用及实现方式。递归组件通过在组件内部调用自身,适用于处理层级结构数据,如菜单和树形控件。动态组件则根据数据变化动态切换组件显示,适用于不同业务逻辑下的组件展示。通过示例,展示了这两种组件的实现方法及其在实际开发中的应用价值。
37 1
|
2月前
|
缓存 前端开发 JavaScript
前端的全栈之路Meteor篇(二):容器化开发环境下的meteor工程架构解析
本文详细介绍了使用Docker创建Meteor项目的准备工作与步骤,解析了容器化Meteor项目的目录结构,包括工程准备、环境配置、容器启动及项目架构分析。提供了最佳实践建议,适合初学者参考学习。项目代码已托管至GitCode,方便读者实践与交流。
|
2月前
|
存储 应用服务中间件 云计算
深入解析:云计算中的容器化技术——Docker实战指南
【10月更文挑战第14天】深入解析:云计算中的容器化技术——Docker实战指南
84 1
|
2月前
|
存储 JavaScript 前端开发
Vue3权限控制全攻略:路由与组件层面的用户角色与权限管理方法深度解析
Vue3权限控制全攻略:路由与组件层面的用户角色与权限管理方法深度解析
218 2

推荐镜像

更多
下一篇
DataWorks