ContextLoaderListener在Spring中的角色/目的?

M S*_*ach 161 java spring web-applications

我正在学习在我的项目中使用的Spring Framework.我在web.xml文件中找到了 ContextLoaderListener条目.但无法弄清楚它对开发人员有何帮助?

ContextLoaderListener的官方文档中,它说它是启动WebApplicationContext.关于WebApplicationContext JavaDocs说:

用于为Web应用程序提供配置的界面.


但我无法理解我在ContextLoaderListener中实现了什么,它在内部初始化WebApplicationContext

根据我的理解,ContextLoaderListener 读取Spring配置文件(使用web.xml中的contextConfigLocation给出的值),解析它并加载该配置文件中定义的单例bean.类似地,当我们想要加载原型bean时,我们将使用相同的webapplication上下文来加载它.因此,我们使用ContextLoaderListener初始化web应用程序,以便我们提前读取/解析/验证配置文件,每当我们想要注入依赖项时,我们都可以毫不拖延地直接执行它.这种理解是否正确?

sou*_*ica 105

你的理解是正确的.这ApplicationContext是你的春豆生活的地方.这个目的ContextLoaderListener是双重的:

  1. 到的生命周期扎ApplicationContext到的生命周期ServletContext

  2. 自动创建ApplicationContext,所以你不必编写显式代码来创建它 - 这是一个方便的功能.

另一个方便的事情ContextLoaderListener是它创建一个WebApplicationContextWebApplicationContext提供对ServletContextvia ServletContextAwarebean和getServletContext方法的访问.

  • 我对你的第二点有疑问.您说ServletContextListener提供对ServletContext的访问.但是,即使web.xml没有ServletContextListener,也可以通过WebApplicationContext访问ServletContext(WebApplicationContext将被自动装配).那么,它究竟与ServletContext有什么关系呢? (2认同)

Vik*_*ram 42

ContextLoaderListener可选的.只是为了让这里的一点:你可以启动一个Spring应用程序而没有配置ContextLoaderListener,只是一个基本的最低web.xmlDispatcherServlet.

这是它的样子:

web.xml中

<?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>
Run Code Online (Sandbox Code Playgroud)

创建一个名为的文件dispatcher-servlet.xml并将其存储在其下WEB-INF.自从我们index.jsp在欢迎列表中提到,请在下面添加此文件WEB-INF.

调度员servlet.xml中

dispatcher-servlet.xml定义你的bean:

<?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>
Run Code Online (Sandbox Code Playgroud)

  • 通常,最好通过反映应用程序体系结构的层来分发bean.表示层的Bean(例如mvc控制器)可以位于dispatcher-servlet.xml中.属于服务层的Bean应该定义applicationContext.xml.这不是一个严格的规则,但实现关注点分离是一种很好的做法. (8认同)
  • 如果要将Servlet文件放在自定义位置或使用自定义名称,而不是默认名称"[servlet-name] -servlet.xml"和"Web-INF /"下的路径,则必须使用它 (6认同)
  • 如果它是可选的,你什么时候_想要_使用它?似乎 Spring Security 要求它使用 DelegatingFilterProxy。 (2认同)
  • @Ramesh Karna我不认为名称和位置变化需要它.我认为当我们初始化多个Dispatcher servlet并且仍希望所有DispaterServlet自己的上下文共享Root上下文时,我们需要使用ContextLoaderListener. (2认同)

xli*_*xli 23

对于一个简单的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>
Run Code Online (Sandbox Code Playgroud)

对于更复杂的Spring应用程序,您有多个已DispatcherServlet定义的应用程序,您可以拥有由以下所有DispatcherServlet定义的共享Spring配置文件ContextLoaderListener:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring/common-config.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
    <servlet-name>mvc1</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/mvc1-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet>
    <servlet-name>mvc2</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/mvc2-config.xmll</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
Run Code Online (Sandbox Code Playgroud)

请记住,ContextLoaderListener执行应用程序上下文的实际初始化工作.

我发现这篇文章有很多帮助: Spring MVC - 应用程序上下文与Web应用程序上下文


Dil*_*epa 10

博客" ContextLoaderListener的目的 - Spring MVC "给出了很好的解释.

根据它,Application-Contexts是分层的,因此DispatcherSerlvet的上下文成为ContextLoaderListener上下文的子代.因此,在控制器层(Struts或Spring MVC)中使用的技术可以独立于根上下文创建的ContextLoaderListener.


sid*_*ani 5

根上下文和子上下文在进一步阅读之前,请理解——

Spring 一次可以有多个上下文。其中之一将是根上下文,所有其他上下文将是子上下文。

所有子上下文都可以访问根上下文中定义的bean;但事实并非如此。根上下文无法访问子上下文 bean。

应用上下文:

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 应用程序,只需一个基本的最小 web.xml 和 DispatcherServlet。

DispatcherServlet DispatcherServlet 本质上是一个 Servlet(它扩展了 HttpServlet),其主要目的是处理与配置的 URL 模式匹配的传入 Web 请求。它接受传入的 URI 并找到控制器和视图的正确组合。所以它是前端控制器。

当您在 spring 配置中定义 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) Application-Contexts 是分层的,WebApplicationContexts 也是如此。请参阅此处的文档。

b) ContextLoaderListener 为 web-application 创建根 web-application-context 并将其放入 ServletContext。无论控制器层(Struts 或 Spring MVC)使用什么技术,此上下文都可用于加载和卸载 spring 管理的 bean。

c) DispatcherServlet 创建它自己的 WebApplicationContext 并且处理程序/控制器/视图解析器由这个上下文管理。

d) 当 ContextLoaderListener 与 DispatcherServlet 一起使用时,如前所述,首先创建根 web-application-context,并且 DispatcherSerlvet 也创建一个 child-context 并附加到根应用程序上下文。请参阅此处的文档。

当我们使用 Spring MVC 并且也在服务层使用 Spring 时,我们提供了两个应用程序上下文。第一个使用 ContextLoaderListener 配置,另一个使用 DispatcherServlet

通常,您将在 DispatcherServlet 上下文中定义所有与 MVC 相关的 bean(控制器和视图等),并通过 ContextLoaderListener 在根上下文中定义所有横切 bean,例如安全、事务、服务等。

有关更多详细信息,请参阅:https : //siddharthnawani.blogspot.com/2019/10/contextloaderlistener-vs.html