Rolle / Zweck von ContextLoaderListener im Frühjahr?

169

Ich lerne Spring Framework , das in meinem Projekt verwendet wird. Ich habe den Eintrag ContextLoaderListener in meiner Datei web.xml gefunden . Aber konnten Sie nicht herausfinden, wie genau es einem Entwickler hilft?

In der offiziellen Dokumentation von ContextLoaderListener heißt es, dass WebApplicationContext gestartet werden soll . In Bezug auf WebApplicationContext sagen JavaDocs:

Schnittstelle zur Konfiguration einer Webanwendung.


Aber ich kann nicht verstehen, was ich mit ContextLoaderListener erreiche, der den WebApplicationContext intern initialisiert .

Gemäß meinem Verständnis , Context liest die Spring - Konfigurationsdatei (mit dem Wert gegeben gegen contextConfigLocation in web.xml ), analysiert es und lädt der Singleton - Bean in dieser Konfigurationsdatei definiert. Wenn wir eine Prototyp-Bean laden möchten, verwenden wir zum Laden denselben Webanwendungskontext. Daher initialisieren wir die Webanwendung mit ContextLoaderListener, sodass wir die Konfigurationsdatei im Voraus lesen / analysieren / validieren und wann immer wir Abhängigkeiten einfügen möchten , können wir dies sofort und ohne Verzögerung tun. Ist dieses Verständnis richtig?

M Sach
quelle
1
kann mir jemand den Unterschied zwischen RequestContextListener und ContextLoaderListener
VdeX

Antworten:

111

Dein Verständnis ist korrekt. Hier ApplicationContextleben Ihre Frühlingsbohnen. Der Zweck des ContextLoaderListenerist zweifach:

  1. den Lebenszyklus des und ApplicationContextan den Lebenszyklus des ServletContextund zu binden

  2. Um die Erstellung des zu automatisieren ApplicationContext, müssen Sie keinen expliziten Code schreiben, um es zu erstellen - es ist eine praktische Funktion.

Eine weitere praktische Sache ContextLoaderListenerist, dass es eine erstellt WebApplicationContextund WebApplicationContextZugriff auf die ServletContextVia ServletContextAwareBeans und die getServletContextMethode bietet .

Sourcedelica
quelle
2
Ich habe Zweifel an Ihrem zweiten Punkt. Sie sagten, ServletContextListener bietet Zugriff auf ServletContext. Selbst wenn web.xml nicht über ServletContextListener verfügt, kann auf ServletContext über WebApplicationContext zugegriffen werden (WebApplicationContext muss automatisch verdrahtet werden). Was genau macht es mit ServletContext?
Sumit Desai
Es schafft die WebApplicationContext. Andernfalls müsste es manuell erstellt werden.
Sourcedelica
nicht ContextLoaderListenerimplementieren eine Methode destroy alle Bohnen , wenn die Web - Container Fahren zu zerstören?
Asgs
ja - das macht es wenn contextDestroyedes aufgerufen wird. Siehe die API-Dokumente.
Sourcedelica
@sourcedelica Ich habe einen Zweifel, nachdem ich dies gelesen habe, habe ich meine Bewerbungen überprüft web.xml. In meiner XML-Datei gibt es zwei Listener ContextLoaderListenerund DispatcherServlet. Ich denke, es gibt keine Notwendigkeit für beides. Ist es sicher zu entfernen, ContextLoaderListenerwarum ich frage, weil die Anwendung seit 7-8 Monaten live ist? web.xml ist hier für Ihre Referenz.
Amogh
43

ContextLoaderListenerist optional . Um hier einen Punkt zu verdeutlichen: Sie können eine Spring-Anwendung starten, ohne sie jemals zu konfigurieren ContextLoaderListener, nur ein grundlegendes Minimum web.xmlmit DispatcherServlet.

So würde es aussehen:

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>

Erstellen Sie eine Datei mit dem Namen dispatcher-servlet.xmlund speichern Sie sie unter WEB-INF. Da wir index.jspin der Begrüßungsliste erwähnt haben , fügen Sie diese Datei unter hinzu WEB-INF.

dispatcher-servlet.xml

In der dispatcher-servlet.xmlDefinition Ihrer Bohnen:

<?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>
Vikram
quelle
2
Wenn es optional ist, wenn würden Sie wollen , es zu benutzen? Es scheint, dass Spring Security die Verwendung von DelegatingFilterProxy erfordert.
David
6
Sie müssen es verwenden, wenn Sie Ihre Servlet-Datei an Ihrem benutzerdefinierten Speicherort oder mit einem benutzerdefinierten Namen anstelle des Standardnamens "[Servlet-Name] -servlet.xml" und des Pfads unter "Web-INF /"
Ramesh Karna
Ist es eine gute Idee, Bean in dispatcher-servlet.xml als applicationContext.xml zu definieren?
Chetan Gole
8
Normalerweise ist es besser, die Beans zu verteilen, indem Sie die Ebenen der Architektur Ihrer Anwendung widerspiegeln. Beans für die Präsentationsschicht (z. B. MVC-Controller) können sich in dispatcher-servlet.xml befinden. Beans, die zur Service-Schicht gehören, sollten als applicationContext.xml definiert werden. Es ist keine strenge Regel, aber es ist eine gute Praxis, um eine Trennung der Bedenken zu erreichen.
Claudio Venturini
2
@Ramesh Karna Ich glaube nicht, dass es für die Änderung von Name und Ort benötigt wird. Ich denke, es ist erforderlich, wenn wir mehrere Dispatcher-Servlets initialisieren und dennoch möchten, dass ein Root-Kontext von allen DispaterServlets-eigenen Kontexten gemeinsam genutzt wird. Dann müssen wir ContextLoaderListener verwenden.
Supernova
23

Für eine einfache Spring-Anwendung müssen Sie nicht ContextLoaderListenerin Ihrem definieren web.xml; Sie können einfach alle Ihre Spring-Konfigurationsdateien ablegen in <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>

Für eine komplexere Spring-Anwendung, in der Sie mehrere DispatcherServletdefiniert haben, können Sie die allgemeinen Spring-Konfigurationsdateien verwenden, die von allen DispatcherServletin 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>

Denken Sie daran, ContextLoaderListenerführt die eigentliche Initialisierungsarbeit für den Stammanwendungskontext aus .

Ich fand, dass dieser Artikel sehr hilfreich ist: Spring MVC - Anwendungskontext vs Webanwendungskontext

xli
quelle
Der hier geteilte Artikel sorgt wirklich für ein tiefes Verständnis der Konzepte
Priyank Thakkar
10

Der Blog " Zweck von ContextLoaderListener - Spring MVC " gibt eine sehr gute Erklärung.

Demnach sind Anwendungskontexte hierarchisch und daher wird der Kontext von DispatcherSerlvet zum untergeordneten Kontext von ContextLoaderListener. Aufgrund dessen kann die in der Controller-Schicht verwendete Technologie (Struts oder Spring MVC) unabhängig vom im Stammkontext erstellten ContextLoaderListener erstellt werden.

Dileepa
quelle
Danke, dass du es geteilt hast, Kumpel .. :)
Deepak Kumar
3

Wenn Sie Ihre Servlet-Datei an Ihrem benutzerdefinierten Speicherort oder mit einem benutzerdefinierten Namen anstelle der Standard-Namenskonvention [servletname]-servlet.xmlund des Pfads unter ablegen möchten, Web-INF/können Sie sie verwenden ContextLoaderListener.

Dungeon_master
quelle
3

ContextLoaderListner ist ein Servlet-Listener, der alle verschiedenen Konfigurationsdateien (Service-Layer-Konfiguration, Persistenz-Layer-Konfiguration usw.) in einen einzelnen Spring-Anwendungskontext lädt.

Dies hilft, Federkonfigurationen auf mehrere XML-Dateien aufzuteilen.

Sobald die Kontextdateien geladen sind, erstellt Spring ein WebApplicationContext-Objekt basierend auf der Bean-Definition und speichert es im ServletContext Ihrer Webanwendung.

Prashant_M
quelle
3

Geben Sie hier die Bildbeschreibung einDieser Bootstrap-Listener dient zum Starten und Herunterfahren von Spring's Root- WebApplicationContext. Da eine Webanwendung über mehrere Dispatcher-Servlets verfügen kann und jedes über einen eigenen Anwendungskontext verfügt, der Controller, Ansichtsauflöser, Handlerzuordnungen usw. enthält. Möglicherweise möchten Sie jedoch Service-Beans und DAO-Beans im Kontext der Stammanwendung haben und in allen untergeordneten Anwendungskontexten verwenden ( Anwendungskontext, der von Dispatcher-Servlets erstellt wurde).

Die zweite Verwendung dieses Listeners ist, wenn Sie die Federsicherheit verwenden möchten.

rulhaniam
quelle
3

Wurzel- und Kinderkontexte Bevor Sie weiterlesen, verstehen Sie bitte, dass -

Der Frühling kann mehrere Kontexte gleichzeitig haben. Einer von ihnen ist der Stammkontext, und alle anderen Kontexte sind untergeordnete Kontexte.

Alle untergeordneten Kontexte können auf die im Stammkontext definierten Beans zugreifen. aber das Gegenteil ist nicht wahr. Der Stammkontext kann nicht auf untergeordnete Kontext-Beans zugreifen.

Anwendungskontext:

applicationContext.xml ist die Stammkontextkonfiguration für jede Webanwendung. Spring lädt die Datei applicationContext.xml und erstellt den ApplicationContext für die gesamte Anwendung. Pro Webanwendung gibt es nur einen Anwendungskontext. Wenn Sie den Namen der Kontextkonfigurationsdatei in web.xml nicht explizit mit dem Parameter contextConfigLocation deklarieren, sucht Spring im Ordner WEB-INF nach applicationContext.xml und löst FileNotFoundException aus, wenn diese Datei nicht gefunden werden konnte.

ContextLoaderListener Führt die eigentliche Initialisierungsarbeit für den Stammanwendungskontext aus. Liest einen Kontextparameter "contextConfigLocation" und übergibt seinen Wert an die Kontextinstanz. Dabei wird er in möglicherweise mehrere Dateipfade analysiert, die durch eine beliebige Anzahl von Kommas und Leerzeichen getrennt werden können, z. B. "WEB-INF / applicationContext1.xml, WEB-INF /" applicationContext2.xml ”. ContextLoaderListener ist optional. Um hier einen Punkt zu verdeutlichen: Sie können eine Spring-Anwendung starten, ohne jemals ContextLoaderListener zu konfigurieren, nur eine grundlegende minimale web.xml mit DispatcherServlet.

DispatcherServlet DispatcherServlet ist im Wesentlichen ein Servlet (es erweitert HttpServlet), dessen Hauptzweck darin besteht, eingehende Webanforderungen zu verarbeiten, die dem konfigurierten URL-Muster entsprechen. Es nimmt eine eingehende URI und findet die richtige Kombination aus Controller und Ansicht. Es ist also der Frontcontroller.

Wenn Sie ein DispatcherServlet in der Frühjahrskonfiguration definieren, stellen Sie eine XML-Datei mit Einträgen von Controller-Klassen, Ansichtszuordnungen usw. mithilfe des Attributs contextConfigLocation bereit.

WebApplicationContext Neben ApplicationContext können in einer Webanwendung mehrere WebApplicationContext vorhanden sein. Mit einfachen Worten, jedes DispatcherServlet, das einem einzelnen WebApplicationContext zugeordnet ist. Die Datei xxx-servlet.xml ist spezifisch für das DispatcherServlet. In einer Webanwendung kann mehr als ein DispatcherServlet für die Verarbeitung der Anforderungen konfiguriert sein. In solchen Szenarien würde für jedes DispatcherServlet eine separate xxx-servlet.xml konfiguriert sein. ApplicationContext.xml ist jedoch für alle Servlet-Konfigurationsdateien gleich. Spring lädt standardmäßig die Datei "xxx-servlet.xml" aus Ihrem WEB-INF-Ordner für Webanwendungen, wobei xxx der Servlet-Name in web.xml ist. Wenn Sie den Namen dieses Dateinamens oder den Speicherort ändern möchten, fügen Sie initi-param mit contextConfigLocation als Parameternamen hinzu.

Vergleich und Beziehung zwischen ihnen:

ContextLoaderListener vs DispatcherServlet

ContextLoaderListener erstellt den Stammanwendungskontext. DispatcherServlet-Einträge erstellen einen untergeordneten Anwendungskontext pro Servlet-Eintrag. Untergeordnete Kontexte können auf Beans zugreifen, die im Stammkontext definiert sind. Beans im Stammkontext können (direkt) nicht auf Beans in untergeordneten Kontexten zugreifen. Alle Kontexte werden zu ServletContext hinzugefügt. Sie können mit der WebApplicationContextUtils-Klasse auf den Stammkontext zugreifen.

Nach dem Lesen der Spring-Dokumentation gilt Folgendes:

a) Anwendungskontexte sind hierarchisch, ebenso wie WebApplicationContexts. Siehe Dokumentation hier.

b) ContextLoaderListener erstellt einen Root-Webanwendungskontext für die Webanwendung und fügt ihn in den ServletContext ein. Dieser Kontext kann zum Laden und Entladen der Spring-Managed-Beans verwendet werden, unabhängig davon, welche Technologie in der Controller-Schicht (Struts oder Spring MVC) verwendet wird.

c) DispatcherServlet erstellt einen eigenen WebApplicationContext und die Handler / Controller / View-Resolver werden von diesem Kontext verwaltet.

d) Wenn ContextLoaderListener zusammen mit DispatcherServlet verwendet wird, wird zuerst ein Root-Webanwendungskontext erstellt, und ein untergeordneter Kontext wird ebenfalls von DispatcherSerlvet erstellt und an den Root-Anwendungskontext angehängt. Siehe Dokumentation hier.

Wenn wir mit Spring MVC arbeiten und Spring auch in der Serviceschicht verwenden, stellen wir zwei Anwendungskontexte bereit. Der erste wird mit ContextLoaderListener und der andere mit DispatcherServlet konfiguriert

Im Allgemeinen definieren Sie alle MVC-bezogenen Beans (Controller und Ansichten usw.) im DispatcherServlet-Kontext und alle übergreifenden Beans wie Sicherheit, Transaktion, Dienste usw. im Stammkontext von ContextLoaderListener.

Weitere Informationen finden Sie hier: https://siddharthnawani.blogspot.com/2019/10/contextloaderlistener-vs.html

Siddharth Nawani
quelle
2

Grundsätzlich können Sie Ihren Stammanwendungskontext und den Webanwendungskontext mit ContextLoaderListner isolieren.

Die mit context param zugeordnete Konfigurationsdatei verhält sich wie die Kontextkonfiguration der Stammanwendung. Die mit dem Dispatcher-Servlet zugeordnete Konfigurationsdatei verhält sich wie der Kontext einer Webanwendung.

In jeder Webanwendung können mehrere Dispatcher-Servlets vorhanden sein, also mehrere Webanwendungskontexte.

In jeder Webanwendung haben wir jedoch möglicherweise nur einen Stammanwendungskontext, der für alle Webanwendungskontexte freigegeben ist.

Wir sollten unsere gemeinsamen Dienste, Entitäten, Aspekte usw. im Kontext der Stammanwendung definieren. Controller, Interceptors usw. befinden sich im relevanten Webanwendungskontext.

Ein Beispiel für web.xml ist

<!-- 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> 

Hier kann die Konfigurationsklasse example.config.AppConfig verwendet werden, um Dienste, Entitäten, Aspekte usw. im Stammanwendungskontext zu konfigurieren, die für alle anderen Webanwendungskontexte freigegeben werden (hier haben wir beispielsweise zwei Konfigurationsklassen für den Webanwendungskontext RestConfig und WebConfig).

PS: Hier ist ContextLoaderListener völlig optional. Wenn wir ContextLoaderListener hier in web.xml nicht erwähnen, funktioniert AppConfig nicht. In diesem Fall müssen wir alle unsere Dienste und Entitäten in WebConfig und Rest Config konfigurieren.

Anil Agrawal
quelle
1

Sie erhalten einen Haken, um Code einzufügen, der zur Bereitstellungszeit der Webanwendung ausgeführt werden soll

Jigar Joshi
quelle
Jigar, eigentlich ist es das, was ich herausfinden möchte. Welche Funktion bietet die Standard-Kontextladeklasse zur Bereitstellungszeit?
M Sach
Ändern Sie Eigenschaften / XML-Dateien und lassen Sie sie zur Laufzeit neu
laden,
1

Listener-Klasse - Hört ein Ereignis ab (z. B. Starten / Herunterfahren des Servers)

ContextLoaderListener -

  1. Hört beim Starten / Herunterfahren des Servers zu
  2. Nimmt die Spring-Konfigurationsdateien als Eingabe und erstellt die Beans gemäß Konfiguration und macht sie bereit (zerstört die Beans beim Herunterfahren)
  3. Konfigurationsdateien können wie folgt in web.xml bereitgestellt werden

    <param-name>contextConfigLocation</param-name>  
    <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>  
Bharanitharan
quelle
1

Im Kontext des Spring Frameworks dient ContextLoaderListener dazu, die anderen Beans in Ihrer Anwendung zu laden, z. B. die Komponenten der mittleren und Datenebene , die das Back-End der Anwendung steuern .

Salahin Rocky
quelle
0

Dein Verständnis ist korrekt. Ich frage mich, warum Sie in ContextLoaderListener keine Vorteile sehen. Beispielsweise müssen Sie eine Sitzungsfactory erstellen (um die Datenbank zu verwalten). Dieser Vorgang kann einige Zeit dauern, daher ist es besser, ihn beim Start auszuführen. Natürlich können Sie dies mit Init-Servlets oder etwas anderem tun, aber der Vorteil von Spring besteht darin, dass Sie die Konfiguration vornehmen, ohne Code zu schreiben.

evg
quelle
0

Wenn wir web.xml ohne ContextLoaderListener schreiben, können wir die Athuntication nicht mit customAuthenticationProvider in Spring Security geben. Da DispatcherServelet der untergeordnete Kontext von ContextLoaderListener ist, ist customAuthenticationProvider der Teil von parentContext, der ContextLoaderListener ist. Der übergeordnete Kontext kann also nicht die Abhängigkeiten des untergeordneten Kontexts haben. Daher ist es empfehlenswert, spring-context.xml in contextparam zu schreiben, anstatt es in initparam zu schreiben.

SathishSakthi
quelle
0

Ich glaube, seine wirkliche Verwendung kommt, wenn Sie mehr als eine Konfigurationsdatei haben möchten oder wenn Sie die Datei xyz.xml anstelle von applicationcontext.xml haben, z

<context-param><param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/training-service.xml, /WEB-INF/training-data.xml</param-value> </context-param>

Ein anderer Ansatz für ContextLoaderListener ist die Verwendung von ContextLoaderServlet wie unten

<servlet> <servlet-name>context</servlet-name> <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet>

user666
quelle