当前位置:网站首页>ContextLoaderListener vs DispatcherServlet
ContextLoaderListener vs DispatcherServlet
2022-07-23 15:05:00 【pilaf1990】
在基于XML的Spring MVC配置中,在web.xml中你需要有ContextLoaderListener和DispatcherServlet的声明。下面让我们来理解一下它们在框架中的作用和不同。
根上下文和子上下文
首先,我们需要知道下面这两个知识:
- Spring在同一时刻可以有多个上下文(contexts)。其中一个是根上下文(Root Context),其它的是子上下文(Child Context)。
- 所有的子上下文可以访问根上下文中定义的bean,但是反过来则不行,即根上下文是不能访问子上下文中的bean的。
DispatcherServlet-Child application context
DispatcherServlet其实就是一个继承了HttpServlet的Servlet,它的主要作用根据请求的url来匹配到符合条件的Controller来处理web请求。所以说它是前端控制器(Front Controller),Spring MVC的Controller是后端控制器。
当使用XML来配置DispatcherServlet时,通常会有如下的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/applicationContext.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>
<!--这儿没有配置value,会默认从 servlet名称-servlet.xml 的文件中获取配置,这儿的servlet名称是app,即从app-servlet.xml文件中获取配置,也可以自己提供一个配置文件路径,如 classpath:my-servlet.xml -->
<param-value></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>
值得一提的是,web应用可以定义任意数量的DispatcherServlet,每个DispatcherServlet控制属于自己namespace下面的mapping,handler等。这些DispatcherServlet会创建属于自己的web application context,它们创建的web application context都是子上下文。
ContextLoaderListener-Root application context
ContextLoaderListener创建一个根上下文,这个根上下文会被DispatcherServlet创建的子上下文共享。前面的web.xml中的属于ContextLoaderListener的部分的配置如下:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
ContextLoaderListener创建的上下文中包含的bean是全局可见的,比如services,repositories,框架相关的beans等等,等根上下文创建完成的时候,会被保存到ServletContext中,作为一个字段,代码参见ContextLoader#initWebApplicationContext方法中
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
//WebApplicationContext接口中定义了
//String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
如果想获取根上下文,可以通过org.springframework.web.context.support.WebApplicationContextUtils提供的方法,如某个Controller的代码:
@Autowired
ServletContext context;
ApplicationContext ac = WebApplicationContextUtils.getWebApplicationContext(context);
ContextLoaderListener 和 DispatcherServlet
下图描述了ContextLoaderListener和DispatcherServlet的关系。

- ContextLoaderListener创建了根上下文。
- DispatcherServlet创建了子上下文。
- 子上下文可以访问根上下文中的bean。
- 根上下文中的bean无法直接访问子上下文中的bean。
- 所有的上下文都被添加到ServletContext中。
- 可以通过WebApplicationContextUtils访问根上下文。
总结
通常,在DispatcherServlet的上下文中定义MVC相关的bean(Controller、View等),所有的横切bean,如安全security、事务transaction、服务service等都定义在ContextLoaderListener创建的根上下文中。
之所以会有这种设计,是因为很少会有在安全、事务相关的bean中访问MVC相关的bean的场景,即很少会有从根上下文的bean中访问子上下文中的bean的场景,但是反过来是很常见的。
参考文章:
1.https://howtodoinjava.com/spring-mvc/contextloaderlistener-vs-dispatcherservlet
2.https://docs.spring.io/spring-framework/docs/current/reference/html/web.html
边栏推荐
- leetcode刷题:动态规划05(不同路径 II)
- [operation] Yan Yi (Internet new technology operation)
- Transfer business append log (transaction propagation behavior)
- nVisual综合布线管理软件与网管软件的区别
- 单细胞论文记录(part19)--A comprehensive comparison on cell-type composition inference for ST data
- Redis distributed lock, it's really impossible without it
- Unity production QR code scanning
- Pymoo learning (4): multi criteria decision making
- LeetCode_455_分发饼干
- 训练和测试的loss不下降,并且精度超低
猜你喜欢

程序员最想干的三件事 |漫画

乘风破浪!金融科技时代下的数字化转型之路
A series of specifications of oneplus 10t were disclosed before the product was released

【redis入门系列】redis的数据类型及相关命令

The larger the convolution kernel, the stronger the performance? An interpretation of replknet model

el-input使用

作为一名后台开发人员,你必须知道的两种过滤器

Unity production QR code scanning

转账业务追加日志(事务的传播行为).

Research and implementation of network multi exit design based on policy routing deployment
随机推荐
Use Preparedstatement to select and display recorded JDBC programs
程序员最想干的三件事 |漫画
[introduction series of redis] data types and related commands of redis
几何参数化重构
【作业】研一(互联网新技术作业)
Three things programmers want to do most | comics
Encapsulate the general connection and query of the project with pymysql
LQR control learning -lqr control matlab official tutorial -lqr controller_ Modeling and analysis of state space system with matlab/simulink
Log slimming operation: from 5g to 1g!
分析optimism重放合约地址攻击事件
“如今,代码数已膨胀至天文级别”
The larger the convolution kernel, the stronger the performance? An interpretation of replknet model
你真的了解Redis的持久化机制吗?
Debug:形参带有Const修饰符号需要注意的地方
Single cell literature learning (part6) -- forestfireclustering for SC sequencing combinations iterative label promotion with
Research and implementation of network multi exit design based on policy routing deployment
LeetCode_724_寻找数组的中心下标
From 5 seconds to 1 second, remember the performance optimization with "very" significant effect once
[ pytorch ] 基本使用丨7. GPU分配丨
元素内容必须由格式正确的字符数据或标记组成