我正在学习正在我的项目中使用的 Spring Framework 。我在 web.xml 文件中找到了 ContextLoaderListener 条目。但无法弄清楚它对开发人员有何帮助?
在ContextLoaderListener的官方文档中,它说要启动 WebApplicationContext 。关于WebApplicationContext JavaDocs说:
为Web应用程序提供配置的界面。
但是我无法理解我使用 ContextLoaderListener 在内部初始化 WebApplicationContext 所实现的目标?
根据我的理解, ContextLoaderListener 读取Spring配置文件(在 web.xml 中为contextConfigLocation提供值),解析它并加载该配置文件中定义的 singleton bean 。类似地,当我们想要加载 prototype bean 时,我们将使用相同的webapplication上下文来加载它。因此,我们使用 ContextLoaderListener 初始化web应用程序,以便我们提前读取/解析/验证配置文件,每当我们想要注入依赖项时,我们都可以毫不拖延地直接执行它。这种理解是否正确?
答案 0 :(得分:100)
您的理解是正确的。 ApplicationContext
是你的Spring bean所在的地方。 ContextLoaderListener
的目的有两个:
将ApplicationContext
的生命周期与ServletContext
和
自动创建ApplicationContext
,因此您不必编写显式代码来创建它 - 它是一个方便的功能。
关于ContextLoaderListener
的另一个方便之处是,它创建了WebApplicationContext
,WebApplicationContext
提供了ServletContext
来自ServletContextAware
bean和{{1}的访问权限方法。
答案 1 :(得分:40)
ContextLoaderListener
可选。只是为了说明一点:你可以在没有配置ContextLoaderListener
的情况下启动Spring应用程序,只需要web.xml
DispatcherServlet
的基本<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID"
version="2.5">
<display-name>Some Minimal Webapp</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
。
以下是它的样子:
<强>的web.xml 强>
dispatcher-servlet.xml
创建一个名为WEB-INF
的文件,并将其存储在index.jsp
下。自从我们在欢迎列表中提到WEB-INF
后,请在dispatcher-servlet.xml
下添加此文件。
<强>调度-servlet.xml中强>
在<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="bean1">
...
</bean>
<bean id="bean2">
...
</bean>
<context:component-scan base-package="com.example" />
<!-- Import your other configuration files too -->
<import resource="other-configs.xml"/>
<import resource="some-other-config.xml"/>
<!-- View Resolver -->
<bean
id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property
name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
定义你的bean:
{{1}}
答案 2 :(得分:23)
对于简单的Spring应用程序,您不必在/product/3
中定义/product/foo
;您可以将所有Spring配置文件放在ContextLoaderListener
:
web.xml
对于更复杂的Spring应用程序,您定义了多个<servlet>
,您可以拥有<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/mvc-core-config.xml, classpath:spring/business-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
中定义的所有DispatcherServlet
共享的公共Spring配置文件: / p>
DispatcherServlet
请记住,ContextLoaderListener
执行 root 应用程序上下文的实际初始化工作。
我发现这篇文章有很多帮助: Spring MVC – Application Context vs Web Application Context
答案 3 :(得分:10)
博客&#34; Purpose of ContextLoaderListener – Spring MVC&#34;给出了很好的解释。
根据它,Application-Contexts是分层的,因此DispatcherSerlvet的上下文成为ContextLoaderListener上下文的子代。因此,在控制器层(Struts或Spring MVC)中使用的技术可以独立于根上下文创建的ContextLoaderListener。
答案 4 :(得分:3)
如果要将Servlet文件放在自定义位置或使用自定义名称,而不是默认命名约定[servletname]-servlet.xml
和Web-INF/
下的路径,则可以使用ContextLoaderListener
。
答案 5 :(得分:3)
ContextLoaderListner是一个Servlet监听器,它将所有不同的配置文件(服务层配置,持久层配置等)加载到单个spring应用程序上下文中。
这有助于在多个XML文件之间拆分弹簧配置。
加载上下文文件后,Spring会根据bean定义创建一个WebApplicationContext对象,并将其存储在Web应用程序的ServletContext中。
答案 6 :(得分:2)
基本上,您可以使用ContextLoaderListner隔离根应用程序上下文和Web应用程序上下文。
使用上下文参数映射的配置文件将表现为根应用程序上下文配置。与调度程序servlet映射的配置文件将表现得像Web应用程序上下文。
在任何Web应用程序中,我们可能有多个调度程序servlet,因此有多个Web应用程序上下文。
但是在任何Web应用程序中,我们可能只有一个与所有Web应用程序上下文共享的根应用程序上下文。
我们应该在根应用程序上下文中定义我们的公共服务,实体,方面等。控制器,拦截器等都在相关的Web应用程序环境中。
示例web.xml是
<!-- language: xml -->
<web-app>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>example.config.AppConfig</param-value>
</context-param>
<servlet>
<servlet-name>restEntryPoint</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>example.config.RestConfig</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>restEntryPoint</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>webEntryPoint</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
</init-param>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>example.config.WebConfig</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>webEntryPoint</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
这里的config class example.config.AppConfig可用于配置将与所有其他Web应用程序上下文共享的根应用程序上下文中的服务,实体,方面等(例如,这里我们有两个Web应用程序上下文配置类RestConfig和WebConfig)
PS:这里ContextLoaderListener是完全可选的。如果我们在这里不提及web.xml中的ContextLoaderListener,AppConfig将无法工作。在这种情况下,我们需要在WebConfig和Rest Config中配置我们的所有服务和实体。
答案 7 :(得分:2)
此Bootstrap监听器将启动并关闭Spring的 root WebApplicationContext。因为Web应用程序可以有多个调度程序servlet,每个都有自己的应用程序上下文,包含控制器,视图解析程序,处理程序映射等。但是您可能希望在根应用程序上下文中使用服务bean,DAO bean并希望在所有子应用程序上下文中使用(调度程序servlet创建的应用程序上下文。
第二次使用此侦听器是您希望使用spring security。
答案 8 :(得分:1)
它将为您提供一些钩子,以便将您希望在Web应用程序部署时执行的代码放入
答案 9 :(得分:0)
您的理解是正确的。我想知道你为什么在ContextLoaderListener中没有看到任何优点。例如,您需要构建会话工厂(以管理数据库)。此操作可能需要一些时间,因此最好在启动时执行此操作。当然你可以用init servlet或其他东西来做,但Spring的方法的优点是你可以在不编写代码的情况下进行配置。
答案 10 :(得分:0)
如果我们编写没有ContextLoaderListener的web.xml,那么我们无法在spring security中使用customAuthenticationProvider进行athuntication。因为DispatcherServelet是ContextLoaderListener的子上下文,所以customAuthenticationProvider是parentContext的一部分,它是ContextLoaderListener。所以父Context不能具有子上下文的依赖关系。因此,最好在contextparam中编写spring-context.xml,而不是在initparam中编写它。
答案 11 :(得分:0)
我相信当你想要拥有多个配置文件或者你有 xyz.xml 文件而不是applicationcontext.xml时,它的实际用途是
<context-param><param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/training-service.xml,
/WEB-INF/training-data.xml</param-value>
</context-param>
ContextLoaderListener的另一种方法是使用ContextLoaderServlet,如下所示
<servlet>
<servlet-name>context</servlet-name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
答案 12 :(得分:0)
监听器类 - 监听事件(例如,服务器启动/关闭)
ContextLoaderListener -
可以在web.xml中提供配置文件
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
答案 13 :(得分:0)
在spring框架的上下文中, ContextLoaderListener 的目的是加载应用程序中的其他bean,例如驱动应用程序后端的中间层和数据层组件。
答案 14 :(得分:0)
根和子上下文 在进一步阅读之前,请了解–
Spring一次可以有多个上下文。其中之一将是根上下文,而所有其他上下文将是子上下文。
所有子上下文都可以访问在根上下文中定义的bean;但事实并非如此。根上下文无法访问子上下文Bean。
ApplicationContext:
applicationContext.xml是每个Web应用程序的根上下文配置。 Spring加载applicationContext.xml文件并为整个应用程序创建ApplicationContext。 每个Web应用程序只有一个应用程序上下文。 如果没有使用contextConfigLocation参数在web.xml中明确声明上下文配置文件名,Spring将在WEB-INF文件夹下搜索applicationContext.xml,如果找不到该文件,则抛出FileNotFoundException。
ContextLoaderListener 对根应用程序上下文执行实际的初始化工作。 读取“ contextConfigLocation”上下文参数,并将其值传递到上下文实例,将其解析为可能由多个逗号和空格分隔的多个文件路径,例如“ WEB-INF / applicationContext1.xml,WEB-INF / applicationContext2.xml”。 ContextLoaderListener是可选的。此处仅说明一点:您无需配置ContextLoaderListener即可启动Spring应用程序,而仅使用DispatcherServlet配置基本的web.xml。
DispatcherServlet DispatcherServlet本质上是一个Servlet(它扩展了HttpServlet),其主要目的是处理与配置的URL模式匹配的传入Web请求。它采用传入的URI并找到控制器和视图的正确组合。所以是前端控制器。
当您在春季配置中定义DispatcherServlet时,您可以使用contextConfigLocation属性为XML文件提供控制器类,视图映射等条目。
WebApplicationContext 除了ApplicationContext,在一个Web应用程序中可以有多个WebApplicationContext。 简单来说,每个DispatcherServlet与单个WebApplicationContext相关联。 xxx-servlet.xml文件特定于DispatcherServlet,并且一个Web应用程序可以配置多个DispatcherServlet来处理请求。 在这种情况下,每个DispatcherServlet都将配置一个单独的xxx-servlet.xml。但是,applicationContext.xml对于所有servlet配置文件都是通用的。 默认情况下,Spring将从您的webapps WEB-INF文件夹中加载名为“ xxx-servlet.xml”的文件,其中xxx是web.xml中的servlet名称。 如果要更改该文件名的名称或更改位置,请添加带有contextConfigLocation作为参数名称的initi-param。
它们之间的比较和关系:
ContextLoaderListener与DispatcherServlet
ContextLoaderListener创建根应用程序上下文。 DispatcherServlet条目为每个Servlet条目创建一个子应用程序上下文。 子上下文可以访问在根上下文中定义的bean。 根上下文中的Bean无法(直接)访问子上下文中的Bean。 所有上下文都添加到ServletContext中。 您可以使用WebApplicationContextUtils类访问根上下文。
在阅读了Spring文档之后,您将了解以下内容:
a)应用程序上下文是层次结构,WebApplicationContexts也是如此。请参阅此处的文档。
b)ContextLoaderListener为Web应用程序创建一个根Web应用程序上下文,并将其放在ServletContext中。无论在控制器层中使用哪种技术(Struts或Spring MVC),都可以使用此上下文加载和卸载Spring管理的bean。
c)DispatcherServlet创建自己的WebApplicationContext,并且处理程序/控制器/视图解析器由该上下文管理。
d)当ContextLoaderListener与DispatcherServlet一起使用时,首先创建一个根Web应用程序上下文,如先前所述,并且一个子上下文也由DispatcherSerlvet创建,并附加到根应用程序上下文。请参阅此处的文档。
当我们使用Spring MVC并在服务层中使用Spring时,我们提供了两个应用程序上下文。第一个使用ContextLoaderListener配置,另一个使用DispatcherServlet
通常,您将在ContextLoaderListener中在DispatcherServlet上下文中定义所有与MVC相关的bean(控制器和视图等),并在根上下文中定义所有跨领域的bean(例如安全性,事务,服务等)。
有关更多详细信息,请参考: https://siddharthnawani.blogspot.com/2019/10/contextloaderlistener-vs.html