Spring中DispacherServlet、WebApplicationContext、ServletContext的关系

解释一:

    要想很好理解这三个上下文的关系,需要先熟悉spring是怎样在web容器中启动起来的。spring的启动过程其实就是其IoC容器的启动过程,对于web程序,IoC容器启动过程即是建立上下文的过程。

spring的启动过程:

  1. 首先,对于一个web应用,其部署在web容器中,web容器提供其一个全局的上下文环境,这个上下文就是ServletContext,其为后面的spring IoC容器提供宿主环境;

  2. 其次,在web.xml中会提供有contextLoaderListener。在web容器启动时,会触发容器初始化事件,此时contextLoaderListener会监听到这个事件,其contextInitialized方法会被调用,在这个方法中,spring会初始化一个启动上下文,这个上下文被称为根上下文,即WebApplicationContext,这是一个接口类,确切的说,其实际的实现类是XmlWebApplicationContext。这个就是spring的IoC容器,其对应的Bean定义的配置由web.xml中的context-param标签指定。在这个IoC容器初始化完毕后,spring以WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE为属性Key,将其存储到ServletContext中,便于获取;

  3. 再次,contextLoaderListener监听器初始化完毕后,开始初始化web.xml中配置的Servlet,这个servlet可以配置多个,以最常见的DispatcherServlet为例,这个servlet实际上是一个标准的前端控制器,用以转发、匹配、处理每个servlet请求。DispatcherServlet上下文在初始化的时候会建立自己的IoC上下文,用以持有spring mvc相关的bean。在建立DispatcherServlet自己的IoC上下文时,会利用WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE先从ServletContext中获取之前的根上下文(即WebApplicationContext)作为自己上下文的parent上下文。有了这个parent上下文之后,再初始化自己持有的上下文。这个DispatcherServlet初始化自己上下文的工作在其initStrategies方法中可以看到,大概的工作就是初始化处理器映射、视图解析等。这个servlet自己持有的上下文默认实现类也是mlWebApplicationContext。初始化完毕后,spring以与servlet的名字相关(此处不是简单的以servlet名为Key,而是通过一些转换,具体可自行查看源码)的属性为属性Key,也将其存到ServletContext中,以便后续使用。这样每个servlet就持有自己的上下文,即拥有自己独立的bean空间,同时各个servlet共享相同的bean,即根上下文(第2步中初始化的上下文)定义的那些bean。

解释二:

在Web容器(比如Tomcat)中配置Spring时,你可能已经司空见惯于web.xml文件中的以下配置代码:
[plain] view plaincopy
  1. <span style="font-family:SimSun;font-size:14px;"><context-param>  
  2.         <param-name>contextConfigLocation</param-name>  
  3.         <param-value>/WEB-INF/applicationContext.xml</param-value>  
  4.     </context-param>  
  5.                                                                                                                                                
  6.     <listener>  
  7.         <listener-class>  
  8.             org.springframework.web.context.ContextLoaderListener  
  9.         </listener-class>  
  10.     </listener>  
  11.                                                                                                                                                
  12.     <servlet>  
  13.         <servlet-name>mvc-dispatcher</servlet-name>  
  14.         <servlet-class>  
  15.             org.springframework.web.servlet.DispatcherServlet  
  16.         </servlet-class>  
  17.         <load-on-startup>1</load-on-startup>  
  18.     </servlet>  
  19.                                                                                                                                            
  20.     <servlet-mapping>  
  21.         <servlet-name>mvc-dispatcher</servlet-name>  
  22.         <url-pattern>/</url-pattern>  
  23.     </servlet-mapping></span>  

    以上配置首先会在ContextLoaderListener中通过<context-param>中的applicationContext.xml创建一个ApplicationContext,再将这个ApplicationContext塞到ServletContext里面,通过ServletContext的setAttribute方法达到此目的,在ContextLoaderListener的源代码中,我们可以看到这样的代码:

[java] view plaincopy
  1. <span style="font-family:SimSun;font-size:14px;">servletContext.setAttribute(  
  2.               WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,  
  3.  this.context);</span>  

    以上由ContextLoaderListener创建的ApplicationContext是共享于整个Web应用程序的,而你可能早已经知道,DispatcherServlet会维持一个自己的ApplicationContext,默认会读取/WEB-INFO/<dispatcherServletName>-servlet.xml文件,而我么也可以重新配置:

[plain] view plaincopy
  1. <span style="font-family:SimSun;font-size:14px;"><servlet>  
  2.     <servlet-name>  
  3.        customConfiguredDispacherServlet  
  4.    </servlet-name>  
  5.    <servlet-class>  
  6.        org.springframework.web.servlet.DispatcherServlet  
  7.    </servlet-class>  
  8.    <init-param>  
  9.        <param-name>  
  10.            contextConfigLocation  
  11.        </param-name>  
  12.        <param-value>  
  13.            /WEB-INF/dispacherServletContext.xml  
  14.        </param-value>  
  15.    </init-param>  
  16.    <load-on-startup>1</load-on-startup>  
  17. </servlet></span>  

    问题是:以上两个ApplicationContext的关系是什么,它们的作用作用范围分别是什么,它们的用途分别是什么?

    ContextLoaderListener中创建ApplicationContext主要用于整个Web应用程序需要共享的一些组件,比如DAO,数据库的ConnectionFactory等。而由DispatcherServlet创建的ApplicationContext主要用于和该Servlet相关的一些组件,比如Controller、ViewResovler等。

    对于作用范围而言,在DispatcherServlet中可以引用由ContextLoaderListener所创建的ApplicationContext,而反过来不行。

    在Spring的具体实现上,这两个ApplicationContext都是通过ServletContext的setAttribute方法放到ServletContext中的。但是,ContextLoaderListener会先于DispatcherServlet创建ApplicationContext,DispatcherServlet在创建ApplicationContext时会先找到由ContextLoaderListener所创建的ApplicationContext,再将后者的ApplicationContext作为参数传给DispatcherServlet的ApplicationContext的setParent()方法,在Spring源代码中,你可以在FrameServlet.java中找到如下代码:

    wac.setParent(parent);

    其中,wac即为由DisptcherServlet创建的ApplicationContext,而parent则为有ContextLoaderListener创建的ApplicationContext。此后,框架又会调用ServletContext的setAttribute()方法将wac加入到ServletContext中。

当Spring在执行ApplicationContext的getBean时,如果在自己context中找不到对应的bean,则会在父ApplicationContext中去找。这也解释了为什么我们可以在DispatcherServlet中获取到由ContextLoaderListener对应的ApplicationContext中的bean。

Spring API中的解释:

public interface WebApplicationContextextends ApplicationContext

Interface to provide configuration for a web application. This is read-only while the application is running, but may be reloaded if the implementation supports this.

This interface adds a getServletContext() method to the generic ApplicationContext interface, and defines a well-known application attribute name that the root context must be bound to in the bootstrap process.

Like generic application contexts, web application contexts are hierarchical. There is a single root context per application, while each servlet in the application (including a dispatcher servlet in the MVC framework) has its own child context.

In addition to standard application context lifecycle capabilities, WebApplicationContext implementations need to detect ServletContextAware beans and invoke the setServletContext method accordingly.

转载于:https://www.cnblogs.com/jiligalaer/p/4443481.html

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

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

相关文章

LeetCode LCS 03. 主题空间(广度优先搜索BFS)

文章目录1. 题目2. 解题1. 题目 「以扣会友」线下活动所在场地由若干主题空间与走廊组成&#xff0c;场地的地图记作由一维字符串型数组 grid&#xff0c;字符串中仅包含 “0"&#xff5e;"5” 这 6 个字符。 地图上每一个字符代表面积为 1 的区域&#xff0c;其中 …

UIImage 裁剪图片和等比列缩放图片

本文转载至 http://blog.csdn.net/cuiweijie3/article/details/9514293 转自 http://www.tedz.me/ios/uiimage-crop-resize-image interface UIImage(UIImageScale)-(UIImage*)getSubImage:(CGRect)rect;-(UIImage*)scaleToSize:(CGSize)size;endimplementation UIImage(UIIma…

python模式匹配算法_详解Python 最短匹配模式

问题你正在试着用正则表达式匹配某个文本模式&#xff0c;但是它找到的是模式的最长可能匹配。 而你想修改它变成查找最短的可能匹配。解决方案这个问题一般出现在需要匹配一对分隔符之间的文本的时候(比如引号包含的字符串)。 为了说明清楚&#xff0c;考虑如下的例子&#xf…

Paddle 基于预训练模型 ERNIE-Gram 实现语义匹配

文章目录1. 导入一些包2. 加载数据3. 数据预处理3.1 获取tokenizer&#xff0c;得到 input_ids, token_type_ids3.2 转换函数、batch化函数、sampler、data_loader4. 编写模型5. 学习率、参数衰减、优化器、loss、评估标准6. 评估函数7. 训练评估8. 保存模型到文件9. 预测10. 多…

j2ee和mysql怎么连接_J2EE数据库连接不再烦恼

刚开始接触j2ee的时候总是为数据库的开关连接问题而烦恼,虽然问题很简单却很是琐碎,于是干脆写成一个类将所有必要的基本操作全部总结进去,以后只要轻松的import一下就可以了啊:)菜鸟们enjoying!import java.sql.Connection;import java.sql.Statement;import java.sql.ResultS…

SQL SERVER PIVOT 行转列、列传行

在数据库操作中&#xff0c;有些时候我们遇到需要实现“行转列”的需求&#xff0c;例如一下的表为某店铺的一周收入情况表&#xff1a; WEEK_INCOME(WEEK VARCHAR(10),INCOME DECIMAL) 我们先插入一些模拟数据&#xff1a; INSERT INTO WEEK_INCOME SELECT 星期一,1000 UNION…

python安装scipy出现红字_windows下安装numpy,scipy遇到的问题总结

1.安装numpy下载numpy编译包&#xff0c;进入该目录下&#xff0c; 调用命令 python setup.py install进行安装&#xff0c;返回错误&#xff1a;error: Unable to find vcvarsall.bat出现这个原因的问题貌似跟vc编译器有关&#xff0c;具体原因没有细究&#xff0c;但是经Goog…

mysql cluster 查看数据库表名称_MySQL Cluster如何创建磁盘表方法解读

MySQL Cluster采用一系列的Disk Data objects来实现磁盘表;接下来为您详细介绍一、概念MySQL Cluster采用一系列的Disk Data objects来实现磁盘表。Tablespaces&#xff1a;作用是作为其他Disk Data objects的容器。Undo log files&#xff1a;存储事务进行回滚需要的信息&…

(运算符) 运算符

& 运算符既可作为一元运算符也可作为二元运算符。 备注 一元 & 运算符返回操作数的地址&#xff08;要求 unsafe 上下文&#xff09;。 为整型和 bool 类型预定义了二进制 & 运算符。 对于整型&#xff0c;& 计算操作数的逻辑按位“与”。 对于 bool 操作数&am…

LeetCode 1903. 字符串中的最大奇数

文章目录1. 题目2. 解题1. 题目 给你一个字符串 num &#xff0c;表示一个大整数。 请你在字符串 num 的所有 非空子字符串 中找出 值最大的奇数 &#xff0c;并以字符串形式返回。如果不存在奇数&#xff0c;则返回一个空字符串 “” 。 子字符串 是字符串中的一个连续的字符…

python模拟qq空间登录_python selenium模拟登录163邮箱和QQ空间

最近在看python网络爬虫&#xff0c;于是我想自己写一个邮箱和QQ空间的自动登录的小程序&#xff0c;下面以登录163邮箱和QQ空间和为例&#xff1a;了解到在Web应用中经常会遇到frame/iframe 表单嵌套页面的应用&#xff0c;WebDriver 只能在一个页面上对元素识别与定位&#x…

mysql分页插件springboot_SpringBoot--使用Mybatis分页插件

1、导入分页插件包和jpa包org.springframework.bootspring-boot-starter-data-jpacom.github.pagehelperpagehelper-spring-boot-starter1.2.52、增加分页配置# 主键自增回写方法,默认值MYSQL,详细说明请看文档mapper:identity: MYSQL# 设置 insert 和 update 中&#xff0c;是…

top 命令详解

作用&#xff1a; 实时动态查看系统的整体运行情况&#xff0c; 是一个综合了多方信息监测系统性能和运行信息的实用工具。 选项&#xff1a;-b 以批处理模式操作-c 显示完整的命令-d 屏幕刷新间隔时间-I 忽略失效过程-s 保密模式-S 累积模式-i 设置时间间隔-u 指定用户…

LeetCode 1904. 你完成的完整对局数

文章目录1. 题目2. 解题1. 题目 一款新的在线电子游戏在近期发布&#xff0c;在该电子游戏中&#xff0c;以 刻钟 为周期规划若干时长为 15 分钟 的游戏对局。 这意味着&#xff0c;在 HH:00、HH:15、HH:30 和 HH:45 &#xff0c;将会开始一个新的对局&#xff0c;其中 HH 用一…

python scipy库函数solve用法_如何在中使用事件scipy.integrate.solve_ivp

我不确定事件处理是否scipy.integrate.solve_ivp工作正常。在下面的例子中&#xff0c;我对一个导数进行积分&#xff0c;得到一个三次多项式&#xff0c;它的根在x-6&#xff0c;x-2和x2。我设置了一个事件函数&#xff0c;返回y&#xff0c;在x值处为零。我希望在解决方案的t…

将MYSQL查询导出到文件

sql文件&#xff1a; set names utf8; select * from xxxxx mysql命令&#xff1a; mysql -h xxxx -uxxxx -p < 4.sql > 4.txt 转载于:https://www.cnblogs.com/aguncn/p/4449969.html

mysql维护计划任务_浅谈MySQL event 计划任务

一、查看event是否开启show variables like %sche%;set global event_scheduler 1;二、-- 设置时区并设置计划事件调度器开启&#xff0c;也可以 event_scheduler onset time_zone 8:00;set global event_scheduler 1;-- 设置该事件使用或所属的数据库base数据库use test;--…

LeetCode 1905. 统计子岛屿(BFS)

文章目录1. 题目2. 解题1. 题目 给你两个 m x n 的二进制矩阵 grid1 和 grid2 &#xff0c;它们只包含 0 &#xff08;表示水域&#xff09;和 1 &#xff08;表示陆地&#xff09;。 一个 岛屿 是由 四个方向 &#xff08;水平或者竖直&#xff09;上相邻的 1 组成的区域。 任…

vue是什么软件_Angular vs React vs Vue:2020年的最佳选择是什么?

在2020年&#xff0c;想象没有HTML&#xff0c;CSS和Javascript的Web开发是不切实际的。 Javascript是Web应用程序前端开发的灵魂。 如果您登陆此页面&#xff0c;那么我认为您在Java语言和Java编程语言的不同框架和库之间感到困惑。企业和软件开发人员最常见的一些查询是&…

Ajax的实现

一、JavaScript的ajax //Ajaxvar xhr;if(window.XMLHttpRequest){ //除IE外的浏览器xhr new XMLHttpRequest()}else{xhr new ActiveXObject("Microsoft.XMLHTTP"); //IE}xhr.open(get,http://demo_get.asp,true); //三个参数&#xff0c;method&#xff0c;…