SpringMvc有几个上下文

news2024/12/29 8:05:10

你好,我是柳岸花明。

SpringMVC作为Spring框架的重要组成部分,其启动流程和父子容器机制是理解整个框架运行机制的关键。本文将通过一系列详细的流程图,深入剖析SpringMVC的启动原理与父子容器的源码结构。

SpringMVC 父子容器

父容器的创建

web.xml 文件中,可以定义如下内容:

<web-app>
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring.xml</param-value>
    </context-param>

    <servlet>
        <servlet-name>app</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring-mvc.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>app</servlet-name>
        <url-pattern>/app/*</url-pattern>
    </servlet-mapping>
</web-app>

这里定义了一个 listenerservlet

ContextLoaderListener 的作用是创建一个 Spring 容器(父容器)。流程如下:

  1. Tomcat启动,解析web.xml时

  2. 发现定义了一个ContextLoaderListener,Tomcat就会执行该listener中的contextInitialized()方法,该方法就会去创建要给Spring容器

  3. 从ServletContext中获取contextClass参数值,该参数表示所要创建的Spring容器的类型

  4. 如果没有配置该参数,那么则会从ContextLoader.properties文件中读取org.springframework.web.context.WebApplicationContext配置项的值,SpringMVC默认提供了一个ContextLoader.properties文件,内容为org.springframework.web.context.support.XmlWebApplicationContext

  5. 所以XmlWebApplicationContext就是要创建的Spring容器类型

  6. 确定好类型后,就用反射调用无参构造方法创建出来一个XmlWebApplicationContext对象

  7. 然后继续从ServletContext中获取contextConfigLocation参数的值,也就是一个spring配置文件的路径

  8. 把spring配置文件路径设置给Spring容器,然后调用refresh(),从而启动Spring容器,从而解析spring配置文件,从而扫描生成Bean对象等

  9. 这样Spring容器就创建出来了

  10. 有了Spring容器后,就会把XmlWebApplicationContext对象作为attribute设置到ServletContext中去,key为WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE

  11. 把Spring容器存到ServletContext中的原因,是为了给Servlet创建出来的子容器来作为父容器的

子容器的创建

Tomcat启动过程中,执行完ContextLoaderListener的contextInitialized()之后,就会创建DispatcherServlet了,web.xml中定义DispatcherServlet时,load-on-startup为1,表示在Tomcat启动过程中要把这个DispatcherServlet创建并初始化出来,而这个过程是比较费时间的,所以要把load-on-startup设置为1,如果不为1,会在servlet接收到请求时才来创建和初始化,这样会导致请求处理比较慢。

  1. Tomcat启动,解析web.xml时
  2. 创建DispatcherServlet对象
  3. 调用DispatcherServlet的init()
  4. 从而调用initServletBean()
  5. 从而调用initWebApplicationContext(),这个方法也会去创建一个Spring容器(就是子容器)
  6. initWebApplicationContext()执行过程中,会先从ServletContext拿出ContextLoaderListener所创建的Spring容器(父容器),记为rootContext
  7. 然后读取contextClass参数值,可以在servlet中的 标签来定义想要创建的Spring容器类型,默认为XmlWebApplicationContext
  8. 然后创建一个Spring容器对象,也就是子容器
  9. 将rootContext作为parent设置给子容器(父子关系的绑定)
  10. 然后读取contextConfigLocation参数值,得到所配置的Spring配置文件路径
  11. 然后就是调用Spring容器的refresh()方法
  12. 从而完成了子容器的创建

SpringMVC 初始化

alt

子容器创建完后,还会调用 DispatcherServletonRefresh() 方法,从 Spring 容器中获取一些特殊类型的 Bean 对象,并设置给 DispatcherServlet 对象中对应的属性,比如 HandlerMappingHandlerAdapter 等。

RequestMappingHandlerAdapter 初始化

RequestMappingHandlerAdapter 的作用是在收到请求时调用请求对应的方法。初始化逻辑如下:

  1. 从 Spring 容器中找到加了 @ControllerAdviceBean 对象。
  2. 解析 Bean 对象中加了 @ModelAttribute@InitBinder 注解的 Method 对象。
  3. 获取实现了 RequestBodyAdviceResponseBodyAdvice 接口的 Bean 对象。
  4. 从 Spring 容器中获取用户定义的 HandlerMethodArgumentResolverHandlerMethodReturnValueHandler,整合为 HandlerMethodArgumentResolverCompositeHandlerMethodReturnValueHandlerComposite 对象。

RequestMappingHandlerMapping 初始化

alt

RequestMappingHandlerMapping 的作用是保存我们定义了哪些 @RequestMapping 方法及对应的访问路径。初始化逻辑如下:

  1. 找出容器中定义的所有的beanName
  2. 根据beanName找出beanType
  3. 判断beanType上是否有@Controller注解或@RequestMapping注解,如果有那么就表示这个Bean对象是一个Handler
  4. 如果是一个Handler,就通过反射找出加了@RequestMapping注解的Method,并解析@RequestMapping注解上定义的参数信息,得到一个对应的RequestMappingInfo对象,然后结合beanType上@RequestMapping注解所定义的path,以及当前Method上@RequestMapping注解所定义的path,进行整合,则得到了当前这个Method所对应的访问路径,并设置到RequestMappingInfo对象中去
  5. 所以,一个RequestMappingInfo对象就对应了一个加了@RequestMapping注解的Method,并且请求返回路径也记录在了RequestMappingInfo对象中
  6. 把当前Handler,也就是beanType中的所有RequestMappingInfo都找到后,就会存到MappingRegistry对象中
  7. 在存到MappingRegistry对象过程中,会像把Handler,也就是beanType,以及Method,生成一个HandlerMethod对象,其实就是表示一个方法
  8. 然后获取RequestMappingInfo对象中的path
  9. 把path和HandlerMethod对象存在一个Map中,属性叫做pathLookup
  10. 这样在处理请求时,就可以同请求路径找到HandlerMethod,然后找到Method,然后执行了

方法参数解析

RequestMappingHandlerAdapter 的初始化逻辑中会设置一些默认的 HandlerMethodArgumentResolver,用于解析各种类型的方法参数。例如:

  1. RequestParamMethodArgumentResolver 解析 @RequestParam 注解的参数。
  2. PathVariableMethodArgumentResolver 解析 @PathVariable 注解的参数。
  3. RequestHeaderMethodArgumentResolver 解析 @RequestHeader 注解的参数。

例如,RequestParamMethodArgumentResolver 的解析逻辑如下:

protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
    HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class);

    if (arg == null) {
        String[] paramValues = request.getParameterValues(name);
        if (paramValues != null) {
            arg = (paramValues.length == 1 ? paramValues[0] : paramValues);
        }
    }
    return arg;
}

这种方法会从请求中获取对应的参数值,并作为方法参数传递。

方法返回值解析

RequestMappingHandlerAdapter 的初始化逻辑中会设置一些默认的 HandlerMethodReturnValueHandler,用于解析各种类型的方法返回值。例如:

  1. ModelAndViewMethodReturnValueHandler 处理返回值为 ModelAndView 的情况。
  2. RequestResponseBodyMethodProcessor 处理方法或类上加了 @ResponseBody 的情况。
  3. ViewNameMethodReturnValueHandler 处理返回值为字符串的情况(无 @ResponseBody)。

我们重点看 RequestResponseBodyMethodProcessor 的逻辑。假如代码如下:

@Controller
public class MController {

    @RequestMapping(method = RequestMethod.GET, path = "/test

"
)
    @ResponseBody
    public User test() {
        User user = new User();
        user.setName("zhangsan");
        return user;
    }
}

RequestResponseBodyMethodProcessor 处理逻辑:

  1. 先从方法返回值中获取对象(如 User)。
  2. BeanFactory 中获取 HttpMessageConverter(如 MappingJackson2HttpMessageConverter)。
  3. 调用 MappingJackson2HttpMessageConverterwrite() 方法将 User 对象写入响应中。

MappingJackson2HttpMessageConverter 是 SpringMVC 默认提供的一个 HttpMessageConverter,用于将对象转换为 JSON。

总结

通过以上流程图和详细解析,我们可以清晰地了解SpringMVC的启动流程和父子容器机制。理解这些核心原理,不仅有助于我们更好地使用SpringMVC框架,也为我们在实际开发中解决问题提供了坚实的理论基础。

👇关注我,下期了解👇 ​ MyBatis源码 ​ ​ alt ​ ​ 回复 222,获取Java面试题合集 ​ 关于我 ​ 一枚爱折腾的Java程序猿,专注Spring干货。把路上的问题记录下来,帮助那些和我一样的人。 ​ 好奇心强,喜欢并深入研究古天文。 ​ 崇尚 个人系统创建,做一些时间越长越有价值的事情。思考 把时间留下来 又 每刻都是新的。

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1939196.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【人工智能】深度剖析AI伦理:强化隐私防线,推动算法公平性的核心议题

文章目录 &#x1f34a;1 人工智能兴起背后的伦理及道德风险1.1 算法偏见与歧视1.2 数据隐私侵权1.3 透明度受限1.4 决策失衡1.5 AI生成内容的危险性 &#x1f34a;2 建构AIGC伦理观&#xff1a;实现人机共创的永续提升2.1 技术手段与伦理预防2.2 即时警告与紧急关停措施2.3 法…

.NET 通过系统影子账户实现权限维持

01阅读须知 此文所节选自小报童《.NET 内网实战攻防》专栏&#xff0c;主要内容有.NET在各个内网渗透阶段与Windows系统交互的方式和技巧。 02基本介绍 03编码实现 在 Windows 操作系统中&#xff0c;影子用户通常是指那些不易被普通用户或系统管理员察觉的隐藏用户账户&…

Linux openEuler_24.03部署MySQL_8.4.0 LTS安装实测验证安装以及测试连接全过程实操手册

Linux openEuler_24.03部署MySQL_8.4.0 LTS安装实测验证安装以及测试连接全过程实操手册 前言: 什么是 MySQL? MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于Oracle 公司。MySQL 是一种关系型数据库管理系统,关系型数据库将数据保存在不同的表中,…

《问题002:报错-“Cannot read property ‘envId‘ of undefined“》

微信小程序云开发报错“Cannot read property ‘envId‘ of undefined“原因及解决办法 原因一&#xff1a;可能是你没有配置envId(解决步骤如下) 1、点击开发者工具上的云开发去获取/复制envId 2、找到配置文件envList.js 原因二&#xff1a;如果你已经完成意思步骤还是不行…

【人工智能】基于yolov5使用OrangePi玩转AI图片识别

前言 机缘巧合之下有幸得到了一块OrangePi AIpro边缘计算开发板&#xff0c;非常感谢香橙派官方推出的OrangePi AIpro边缘计算开发板。Orange Pi AI Pro 开发板是由香橙派和华为合作开发的高性能AI开发板&#xff0c;搭载了昇腾AI处理器&#xff0c;提供了8TOPS INT8的计算能力…

用html做python教程01

用html做python教程01 前言开肝构思实操额外修饰更换字体自适应 最后 前言 今天打开csdn的时候&#xff0c;看见csdn给我推荐了一个python技能书。 说实话&#xff0c;做得真不错。再看看我自己&#xff0c;有亿点差距&#x1f61f;。 开肝 先创建一个文件&#xff0c;后缀…

【大数据面试题】37 Doris 是怎么保证性能的?

一步一个脚印&#xff0c;一天一道大数据面试题 博主希望能够得到大家的点赞收藏支持&#xff01;非常感谢 点赞&#xff0c;收藏是情分&#xff0c;不点是本分。祝你身体健康&#xff0c;事事顺心&#xff01; Doris 是当下大热的 MPP 数据库&#xff0c;下面来聊聊它如何保证…

力扣每日一题1186. 删除一次得到子数组最大和【动态规划】

本题的核心在于对于每个元素&#xff0c;我们分别考虑保留和删除两种状态&#xff0c;并根据前面的状态转移来更新当前状态。最后&#xff0c;遍历所有元素&#xff0c;找到最大和即可。 状态定义 dp[i][0] 表示以第 i 个元素结尾且未删除元素的子数组的最大和。dp[i][1] 表示…

ClamAV:Linux病毒查杀软件安装使用

简介&#xff1a;ClamAV是一个开源防病毒工具包&#xff0c;专为邮件网关上的电子邮件扫描而设计。它提供了许多实用程序&#xff0c;包括一个灵活且可扩展的多线程守护进程、一个命令行扫描程序和用于自动数据库更新的高级工具。该软件包的核心是以共享库的形式提供的防病毒引…

大豆叶部病害soybean-目标检测数据集(包括VOC格式、YOLO格式)

大豆叶部病害soybean-目标检测数据集&#xff08;包括VOC格式、YOLO格式&#xff09; 数据集&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1DIq2vp-z_fM7Xj_nsBAGBQ?pwdk373 提取码&#xff1a;k373 数据集信息介绍&#xff1a; 共有 1232 张图像和一一对应的标注…

python 打包

#导出依赖文件列表 pip freeze > requirements.txt #安装对应文件 pip install -r requirements.txt #将依赖打成对应whl文件 pip wheel --wheel-dir ./dist -r ./requirements.txt #安装whl文件 pip install …whl

消费金融系统开发回忆录

架构设计图 整个支付链路上的功能 支付系统应该有&#xff1a;账户管理、渠道管理、支付管理、对账管理、清算管理、结算管理 一笔支付订单&#xff0c;在支付系统侧就是要记录清楚&#xff0c;谁发起的、对哪个商品进行支付、通过哪个渠道支付、支付时间、支付结果等…

【Linux知识点汇总】07 Linux系统防火墙相关命令,关闭和开启防火墙、开放端口号

​完整系列文章目录 【Linux知识点汇总】 心血来潮突然想起之前写过的系列文章【Linux知识点汇总】还未完结&#xff0c;那么今天就继续吧 说明&#xff1a;这个系列的内容&#xff0c;在系列【Linux服务器Java环境搭建】中会经常用到&#xff0c;大家可以自行查找相关命令 一、…

SMU Summer 2024 div2 2nd

文章目录 The Second Week一、前言二、算法1.二分图匹配/匈牙利算法<1>&#xff08;[ZJOI2007]矩阵游戏&#xff09;<2>&#xff08;有大家喜欢的零食吗&#xff09; 2.优先队列<1>&#xff08;Running Median&#xff09;<2>&#xff08;旅途的终点&a…

运维团队如何高效监控容器化环境中的PID及其他关键指标

随着云计算和容器化技术的快速发展&#xff0c;越来越多的企业开始采用容器化技术来部署和管理应用程序。然而&#xff0c;容器化环境的复杂性和动态性给运维团队带来了前所未有的挑战。本文将从PID&#xff08;进程标识符&#xff09;监控入手&#xff0c;探讨运维团队如何高效…

下载最新版Anaconda、安装、更换源、配置虚拟环境并在vscode中使用

文章目录 进入官网进入下载页安装更换源配置虚拟环境env安装包requests在vscode中使用虚拟环境 进入官网 https://repo.anaconda.com/ 或进入清华大学下载 https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/ 进入下载页 安装 更换源 查看已经存在的镜像源 bash cond…

windows实现端口转发

最近在做界面开发时&#xff0c;想要直接在手机上看看实际效果&#xff0c;由于我的服务器是放在虚拟机上的&#xff0c;所以需要在window上面做个端口转发&#xff0c;这就需要用到netsh命令。 添加端口转发 netsh interface portproxy add v4tov4 listenport8080 listenadd…

广州机房搬迁网络部署方案

新机房网络部署应包括核心模块、业务模块、光传输模块、安全模块、流量采集模块、路由模块、带外管理模块等&#xff0c;每个模块都根据业务需求规划成多个POD&#xff08;Point Of Delivery&#xff0c;基本物理设计单元&#xff09;。 核心模块部署主要实现各业务模块的高速互…

语义分割——为什么单通道8bit灰度图像能显示多种色块???

目录 一、问题二、解答2.1 标签图的实际存储格式2.2 标签图的显示颜色2.3 颜色映射示例 三、应用颜色映射3.1 OpenCV显示标签图3.2 Matplotlib显示标签图 四、总结 一、问题 大家在做语义分割时不知道有没有这样的疑惑&#xff0c;使用打标签工具后&#xff0c;标签图是单通道…

大气热力学(15)——热力学图的应用之三(逆温)

文章目录 15.1 逆温的概念15.2 辐射逆温15.2.1 辐射逆温的形成原因15.2.2 辐射逆温的生消过程15.2.3 辐射逆温在探空图的特征15.2.4 辐射雾的形成与特征 15.3 平流逆温15.3.1 平流逆温的形成原因15.3.2 平流雾的形成与特征 15.4 湍流逆温15.4.1 湍流逆温的形成原因15.4.2 湍流逆…