Unterschied zwischen applicationContext.xml und spring-servlet.xml in Spring Framework

373
  • Sind applicationContext.xmlund spring-servlet.xmlirgendwie in Spring Framework verwandt?
  • Werden die in deklarierten Eigenschaftendateien applicationContext.xmlverfügbar sein DispatcherServlet?
  • Warum brauche ich *-servlet.xmlüberhaupt eine? Warum reicht applicationContext.xmlallein nicht aus?
user448070
quelle
1
Sehen Sie das auch. stackoverflow.com/questions/11708967/…
Sanghyun Lee

Antworten:

430

Mit Spring können Sie mehrere Kontexte in einer Eltern-Kind-Hierarchie definieren.

Das applicationContext.xmldefiniert die Beans für den "Root-Webapp-Kontext", dh den Kontext, der der Webapp zugeordnet ist.

Das spring-servlet.xml(oder wie auch immer Sie es nennen) definiert die Beans für den App-Kontext eines Servlets. In einer Webanwendung können viele davon vorhanden sein, eine pro Federservlet (z. B. spring1-servlet.xmlfür Servlet spring1, spring2-servlet.xmlfür Servlet spring2).

Bohnen in spring-servlet.xmlkönnen auf Bohnen verweisen applicationContext.xml, aber nicht umgekehrt.

Alle Spring MVC-Controller müssen in den spring-servlet.xmlKontext gehen.

In den meisten einfachen Fällen ist der applicationContext.xmlKontext nicht erforderlich. Es wird im Allgemeinen verwendet, um Beans zu enthalten, die von allen Servlets in einer Webanwendung gemeinsam genutzt werden. Wenn Sie nur ein Servlet haben, ist es nicht wirklich sinnvoll, es sei denn, Sie haben eine bestimmte Verwendung dafür.

Skaffman
quelle
30
Warum sollten Sie mehrere Federservlets haben?
NimChimpsky
5
mächtig starke Antwort (wegen der Prägnanz)
amphibient
35
@NimChimpsky Manchmal ist es nützlich, Teile Ihrer Anwendung zu trennen, die andernfalls im selben Kontext in Konflikt geraten könnten. Als Beispiel haben Sie möglicherweise ReST-Dienste und Standardansichten. Möglicherweise haben Sie dann unterschiedliche Ansichtsauflöser oder Sicherheitsbedenken für die Dienste in Bezug auf die Ansichten.
Brett Ryan
12
Die Leute sollten diese Antwort sehen, bevor sie die Dokumentation lesen und Apps entwickeln! Im Normalfall müssen ContextLoaderListener und contextConfigLocation überhaupt nicht vorhanden sein, nur DispatcherServlet!
Ruruskyi
24
In vielen Tutorials enthält contextConfigLocation sowohl dispatcher-servlet.xml als auch DispatcherServlet. Dies führt dazu, dass Bohnen zweimal initialisiert werden!
Ruruskyi
106

Szenario 1

In der Client-Anwendung (Anwendung ist keine Webanwendung, z. B. Swing-App)

private static ApplicationContext context = new  ClassPathXmlApplicationContext("test-client.xml");

context.getBean(name);

Keine Notwendigkeit für web.xml . ApplicationContext als Container zum Abrufen des Bean-Dienstes. Kein Webserver-Container erforderlich. In test-client.xml kann es eine einfache Bean ohne Remoting und eine Bean mit Remoting geben.

Schlussfolgerung : In Szenario 1 applicationContext und DispatcherServletsind nicht verwandt.

Szenario 2

In einer Serveranwendung (auf dem Server bereitgestellte Anwendung, z. B. Tomcat). Zugriff auf den Dienst über Remoting vom Client-Programm (z. B. Swing-App)

Definieren Sie den Listener in web.xml

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

Beim Serverstart werden ContextLoaderListenerin applicationContext.xml definierte Beans instanziiert .

Angenommen, Sie haben in applicationContext.xml Folgendes definiert :

<import resource="test1.xml" />
<import resource="test2.xml" />
<import resource="test3.xml" />
<import resource="test4.xml" />

Die Beans werden aus allen vier Konfigurationsdateien test1.xml , test2.xml , test3.xml , test4.xml instanziiert .

Schlussfolgerung : In Szenario 2 applicationContext und DispatcherServletsind nicht verwandt.

Szenario 3

In einer Webanwendung mit Feder MVC.

In web.xml definieren Sie:

<servlet>
    <servlet-name>springweb</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>    
</servlet>

<servlet-mapping>
    <servlet-name>springweb</servlet-name>
    <url-pattern>*.action</url-pattern>
</servlet-mapping>

Wenn Tomcat gestartet wird, werden die in springweb-servlet.xml definierten Beans instanziiert. DispatcherServleterstreckt sich FrameworkServlet. In FrameworkServletBean erfolgt die Instanziierung für Springweb. In unserem Fall ist springweb FrameworkServlet.

Schlussfolgerung : In Szenario 3 applicationContext und DispatcherServletsind nicht verwandt.

Szenario 4

In Webanwendung mit Feder MVC. springweb-servlet.xml für servlet und applicationContext.xml für den Zugriff auf den Geschäftsdienst innerhalb des Serverprogramms oder für den Zugriff auf den DB-Dienst in einem anderen Serverprogramm.

In web.xml sind folgende definiert:

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
    <servlet-name>springweb</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>        
</servlet>

<servlet-mapping>
    <servlet-name>springweb</servlet-name>
    <url-pattern>*.action</url-pattern>
</servlet-mapping>

ContextLoaderListenerInstanziiert beim Start des Servers die in applicationContext.xml definierten Beans . vorausgesetzt, Sie haben hier erklärt:

<import resource="test1.xml" />
<import resource="test2.xml" />
<import resource="test3.xml" />
<import resource="test4.xml" />

Die Beans werden alle aus allen vier test1.xml , test2.xml , test3.xml , test4.xml instanziiert . Nach Abschluss der in applicationContext.xml definierten Bean-Instanziierung werden in springweb-servlet.xml definierte Beans instanziiert.

Die Instanziierungsreihenfolge lautet also: Root (Anwendungskontext), dann FrameworkServlet.

Jetzt sollte klar sein, warum sie in welchem ​​Szenario wichtig sind.

Abishkar Bhattarai
quelle
10
+1. Sehr gut. Ich habe nach dieser Art von Vergleich gesucht, aber nie gefunden.
Ninad Pingale
@abishkar bhattarai sehr gut, meine Frage ist: Was ist, wenn @ Component und @ Value Annotation verwendet werden, um Bean zu erstellen, wenn "Szenario 4"
Lawrence
springweb DispatcherServletwird nicht aufgerufen, wenn die URL nicht mit .action endet?
Asif Mushtaq
@lawrence Sie müssen weiterhin den Klassenpfad in der Datei springweb-servlet.xml angeben, damit Spring diese Komponente in seinem Scan finden kann.
Veritas
54

Ein weiterer Punkt, den ich hinzufügen möchte. In spring-servlet.xmlenthalten ist der Komponentenscan für das Controller-Paket. Im folgenden Beispiel enthalten wir Filteranmerkungen für das Controller-Paket.

<!-- Scans for annotated @Controllers in the classpath -->
<context:component-scan base-package="org.test.web" use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

In applicationcontext.xmlfügen wir Filter für das verbleibende Paket ohne Controller hinzu.

<context:component-scan base-package="org.test">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
Raje
quelle
9
Warum ? Warum nicht einfach das Ganze einmal scannen?
NimChimpsky
3
@NimChimpsky Sie müssen @ControllerBeans im Servlet-Kontext scannen (erforderlich von Spring MVC).
Tuukka Mustonen
3
Warum kann das Ganze nicht zweimal? Warum einschließen / ausschließen?
Mike Rylander
8
Man sollte auch das Attribut use-default-filter = "false" in spring-servlet.xml hinzufügen
Rakesh Waghela
4
Rakesh Waghela hat Punkt. Ohne dieses Attribut werden Controller-Beans zweimal erstellt. Erstens in appContext und zweitens in servletContext
UltraMaster
12

In einfachen Worten,

applicationContext.xmlDefiniert die Beans, die von allen Servlets gemeinsam genutzt werden. Wenn Ihre Anwendung mehr als ein Servlet hat, ist applicationContext.xmles sinnvoller , die allgemeinen Ressourcen im zu definieren .

spring-servlet.xmlDefiniert die Beans, die sich nur auf dieses Servlet beziehen. Hier ist es das Dispatcher-Servlet. Daher müssen Ihre Spring MVC-Controller in dieser Datei definiert sein.

Es ist nichts Falsches daran, alle Beans in der zu definieren, spring-servlet.xmlwenn Sie nur ein Servlet in Ihrer Webanwendung ausführen.

Krishna
quelle
3
Ich kann alle Beans in spring-servlet.xml definieren, aber es sollte auch applicationContext.xml geben, die in diesem Fall leer sein kann (ohne Beans). Richtig?
Mikhail Kopylov
6

Wenn Sie in der Servlet-Technologie eine Eingabe an ein bestimmtes Servlet übergeben möchten, müssen Sie den init-Parameter wie im folgenden Code übergeben.

 <servlet>
    <servlet-name>DBController</servlet-name>
    <servlet-class>com.test.controller.DBController</servlet-class>
    <init-param>
        <param-name>username</param-name>
        <param-value>John</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>DBController</servlet-name>
    <url-pattern>/DBController</url-pattern>
</servlet-mapping>

Wenn Sie einige Eingaben übergeben möchten, die für alle Servlets gleich sind, müssen Sie diesmal die Kontextparameter konfigurieren. Beispiel

 <context-param>
    <param-name>email</param-name>
    <param-value>admin@example.com</param-value>
</context-param>

Genau so müssen wir, wenn wir mit Spring MVC arbeiten, dem von Spring bereitgestellten vordefinierten Servlet, das DispatcherServlet über init param ist, einige Informationen bereitstellen. Die Konfiguration ist also wie folgt: Hier stellen wir DispatcherServlet die Datei spring-servlet.xml als init-Parameter zur Verfügung.

 <?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_3_0.xsd"
    id="WebApp_ID" version="3.0">
    <display-name>Spring MVC App</display-name>

    <servlet>
        <servlet-name>SpringController</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>SpringController</servlet-name>
        <url-pattern>*.htm</url-pattern>
    </servlet-mapping>
</web-app>

Wieder brauchen wir einen Kontextparameter. Das gilt für die gesamte Anwendung. So können wir den Stammkontext applicationcontext.xml bereitstellen. Die Konfiguration lautet wie folgt:

    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationcontext.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
        <servlet-name>SpringController</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>SpringController</servlet-name>
        <url-pattern>*.htm</url-pattern>
    </servlet-mapping>
Rajanikanta Pradhan
quelle
4

Anwendungskontexte bieten eine Möglichkeit zum Auflösen von Textnachrichten, einschließlich der Unterstützung von i18n dieser Nachrichten. Anwendungskontexte bieten eine allgemeine Möglichkeit zum Laden von Dateiressourcen, z. B. Bildern. Anwendungskontexte können Ereignisse in Beans veröffentlichen, die als Listener registriert sind. Bestimmte Operationen am Container oder an den Beans im Container, die programmgesteuert mit einer Bean Factory behandelt werden müssen, können in einem Anwendungskontext deklarativ behandelt werden. ResourceLoader-Unterstützung: Die Ressourcenschnittstelle von Spring bietet eine flexible generische Abstraktion für den Umgang mit Ressourcen auf niedriger Ebene. Ein Anwendungskontext selbst ist ein ResourceLoader. Daher bietet er einer Anwendung Zugriff auf implementierungsspezifische Ressourceninstanzen. MessageSource-Unterstützung: Der Anwendungskontext implementiert MessageSource, eine Schnittstelle zum Abrufen lokalisierter Nachrichten.

Sujata
quelle