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

简介: 解析 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,后续会有更多实战、源码、架构干货分享!

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

目录
相关文章
|
4月前
|
Web App开发 前端开发 JavaScript
前端新利器:CSS容器查询——让组件真正“自适应
前端新利器:CSS容器查询——让组件真正“自适应
303 83
|
8月前
|
前端开发 API 开发者
harmonyOS基础- 快速弄懂HarmonyOS ArkTs基础组件、布局容器(前端视角篇)
本文由黑臂麒麟(6年前端经验)撰写,介绍ArkTS开发中的常用基础组件与布局组件。基础组件包括Text、Image、Button等,支持样式设置如字体颜色、大小和加粗等,并可通过Resource资源引用统一管理样式。布局组件涵盖Column、Row、List、Grid和Tabs等,支持灵活的主轴与交叉轴对齐方式、分割线设置及滚动事件监听。同时,Tabs组件可实现自定义样式与页签切换功能。内容结合代码示例,适合初学者快速上手ArkTS开发。参考华为开发者联盟官网基础课程。
623 75
harmonyOS基础- 快速弄懂HarmonyOS ArkTs基础组件、布局容器(前端视角篇)
|
3月前
|
Kubernetes Cloud Native 持续交付
Docker:轻量级容器化技术解析
Docker:轻量级容器化技术解析
|
11月前
|
前端开发 JavaScript
React 步骤条组件 Stepper 深入解析与常见问题
步骤条组件是构建多步骤表单或流程时的有力工具,帮助用户了解进度并导航。本文介绍了在React中实现简单步骤条的方法,包括基本结构、状态管理、样式处理及常见问题解决策略,如状态管理库的使用、自定义Hook的提取和CSS Modules的应用,以确保组件的健壮性和可维护性。
252 17
|
5月前
|
存储 缓存 安全
Java 集合容器常见面试题及详细解析
本文全面解析Java集合框架,涵盖基础概念、常见接口与类的特点及区别、底层数据结构、线程安全等内容。通过实例讲解List(如ArrayList、LinkedList)、Set(如HashSet、TreeSet)、Map(如HashMap、TreeMap)等核心组件,帮助读者深入理解集合容器的使用场景与性能优化。适合准备面试或提升开发技能的开发者阅读。
85 0
|
7月前
|
弹性计算 Java Maven
从代码到容器:Cloud Native Buildpacks技术解析
Cloud Native Buildpacks(CNB)是一种标准化、云原生的容器镜像构建系统,旨在消除手动编写Dockerfile,提供可重复、安全且高效的构建流程。它通过分层策略生成符合OCI标准的镜像,实现应用与基础镜像解耦,并自动化依赖管理和更新。阿里云应用管理支持通过CNB技术一键部署应用至ECS,简化构建和运行流程。
|
8月前
|
索引
【Flutter 开发必备】AzListView 组件全解析,打造丝滑索引列表!
在 Flutter 开发中,AzListView 是实现字母索引分类列表的理想选择。它支持 A-Z 快速跳转、悬浮分组标题、自定义 UI 和高效性能,适用于通讯录、城市选择等场景。本文将详细解析 AzListView 的核心参数和实战示例,助你轻松实现流畅的索引列表。
330 7
|
10月前
|
Kubernetes Linux 虚拟化
入门级容器技术解析:Docker和K8s的区别与关系
本文介绍了容器技术的发展历程及其重要组成部分Docker和Kubernetes。从传统物理机到虚拟机,再到容器化,每一步都旨在更高效地利用服务器资源并简化应用部署。容器技术通过隔离环境、减少依赖冲突和提高可移植性,解决了传统部署方式中的诸多问题。Docker作为容器化平台,专注于创建和管理容器;而Kubernetes则是一个强大的容器编排系统,用于自动化部署、扩展和管理容器化应用。两者相辅相成,共同推动了现代云原生应用的快速发展。
2464 11
|
11月前
|
前端开发 UED
React 文本区域组件 Textarea:深入解析与优化
本文介绍了 React 中 Textarea 组件的基础用法、常见问题及优化方法,包括状态绑定、初始值设置、样式自定义、性能优化和跨浏览器兼容性处理,并提供了代码案例。
358 9
|
12月前
|
安全 持续交付 Docker
深入理解并实践容器化技术——Docker 深度解析
深入理解并实践容器化技术——Docker 深度解析
459 2

热门文章

最新文章

推荐镜像

更多
  • DNS
  • 下一篇
    开通oss服务