Différence entre applicationContext.xml et spring-servlet.xml dans Spring Framework

373
  • Sont applicationContext.xmlet sont spring-servlet.xmlliés de toute façon dans Spring Framework?
  • Les fichiers de propriétés déclarés dans applicationContext.xmlseront-ils disponibles DispatcherServlet?
  • Sur une note connexe, pourquoi ai-je besoin d'un *-servlet.xml? Pourquoi applicationContext.xmlseul est- il insuffisant?
user448070
la source
1
Voyez cela aussi. stackoverflow.com/questions/11708967/…
Sanghyun Lee

Réponses:

430

Spring vous permet de définir plusieurs contextes dans une hiérarchie parent-enfant.

Le applicationContext.xmldéfinit les beans pour le "contexte racine webapp", c'est-à-dire le contexte associé à la webapp.

Le spring-servlet.xml(ou tout autre nom que vous appelez) définit les beans pour le contexte d'application d'un servlet. Il peut y en avoir plusieurs dans une webapp, une par servlet Spring (par exemple spring1-servlet.xmlpour servlet spring1, spring2-servlet.xmlpour servlet spring2).

Les beans in spring-servlet.xmlpeuvent référencer les beans in applicationContext.xml, mais pas l'inverse.

Tous les contrôleurs Spring MVC doivent aller dans le spring-servlet.xmlcontexte.

Dans la plupart des cas simples, le applicationContext.xmlcontexte n'est pas nécessaire. Il est généralement utilisé pour contenir des beans partagés entre tous les servlets d'une application Web. Si vous n'avez qu'une seule servlet, il n'y a pas vraiment d'intérêt, à moins que vous n'en ayez une utilisation spécifique.

skaffman
la source
30
pourquoi auriez-vous plusieurs servlets à ressort?
NimChimpsky
5
puissante réponse puissante (à cause de la brièveté)
amphibient
35
@NimChimpsky, il est parfois utile de séparer les parties de votre application qui pourraient autrement entrer en conflit dans le même contexte. Par exemple, vous pouvez avoir des services ReST et des vues standard, vous pouvez alors avoir différents résolveurs de vues ou problèmes de sécurité pour les services quant aux vues.
Brett Ryan
12
Les gens devraient voir cette réponse avant de lire la documentation et de développer des applications! Dans des cas normaux, il n'est pas nécessaire d'avoir ContextLoaderListener et contextConfigLocation, juste DispatcherServlet!
ruruskyi
24
Dans de nombreux didacticiels, contextConfigLocation contient dispatcher-servlet.xml ainsi que DispatcherServlet. Cela provoque l'initialisation des beans deux fois!
ruruskyi
106

Scénario 1

Dans l'application client (l'application n'est pas une application Web, par exemple peut être une application swing)

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

context.getBean(name);

Pas besoin de web.xml . ApplicationContext comme conteneur pour obtenir le service de bean. Pas besoin de conteneur de serveur Web. Dans test-client.xml, il peut y avoir un bean simple sans accès à distance, un bean avec accès à distance.

Conclusion : dans le scénario 1 applicationContext et DispatcherServletne sont pas liés.

Scénario 2

Dans une application serveur (application déployée sur le serveur par exemple Tomcat). Service accessible via la télécommande depuis le programme client (par exemple, l'application Swing)

Définir l'écouteur dans web.xml

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

Au démarrage du serveur, ContextLoaderListenerinstancie les beans définis dans applicationContext.xml .

En supposant que vous ayez défini les éléments suivants dans applicationContext.xml :

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

Les beans sont instanciés à partir des quatre fichiers de configuration test1.xml , test2.xml , test3.xml , test4.xml .

Conclusion : dans le scénario 2 applicationContext et DispatcherServletne sont pas liés.

Scénario 3

Dans une application web avec ressort MVC.

Dans web.xml, définissez:

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

Au démarrage de Tomcat, les beans définis dans springweb-servlet.xml sont instanciés. DispatcherServlets'étend FrameworkServlet. Dans le FrameworkServletharicot, l'instanciation a lieu pour le springweb. Dans notre cas, springweb est FrameworkServlet.

Conclusion : dans le scénario 3 applicationContext et DispatcherServletne sont pas liés.

Scénario 4

Dans l'application web avec ressort MVC. springweb-servlet.xml pour servlet et applicationContext.xml pour accéder au service métier dans le programme serveur ou pour accéder au service DB dans un autre programme serveur.

Dans web.xml, les éléments suivants sont définis:

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

Au démarrage du serveur, ContextLoaderListenerinstancie les beans définis dans applicationContext.xml ; en supposant que vous avez déclaré ici:

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

Les beans sont tous instanciés à partir des quatre test1.xml , test2.xml , test3.xml , test4.xml . Une fois l'instanciation du bean définie dans applicationContext.xml terminée , les beans définis dans springweb-servlet.xml sont instanciés.

Donc l'ordre d'instanciation est: la racine (contexte d'application), puis FrameworkServlet.

Maintenant, il devrait être clair pourquoi ils sont importants dans quel scénario.

abishkar bhattarai
la source
10
+1. Très bien, je cherchais ce type de comparaison, mais jamais trouvé.
Ninad Pingale
@abishkar bhattarai très bien, ma question est: alors qu'est-ce qui se passe si vous utilisez @ Component et @ Value annotation pour créer un bean lorsque "Scenario 4"
lawrence
springweb DispatcherServletne sera pas appelé si l'url ne se termine pas par .action?
Asif Mushtaq
@lawrence Vous devrez toujours spécifier le chemin d'accès aux classes dans le fichier springweb-servlet.xml afin que Spring puisse trouver ce composant dans son analyse.
veritas
54

Un dernier point que je veux ajouter. En spring-servlet.xmlnous incluons analyse composants pour package Controller. Dans l'exemple suivant, nous incluons une annotation de filtre pour le package du contrôleur.

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

Dans applicationcontext.xmlnous ajoutons un filtre pour le paquet restant à l'exclusion du contrôleur.

<context:component-scan base-package="org.test">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
Raje
la source
9
Pourquoi ? Pourquoi ne pas simplement scanner le tout une fois?
NimChimpsky
3
@NimChimpsky Vous devez analyser les @Controllerbeans dans le contexte de servlet (requis par Spring MVC).
Tuukka Mustonen
3
Pourquoi pas le tout deux fois? Pourquoi inclure / exclure?
Mike Rylander
8
On devrait également ajouter l'attribut use-default-filters = "false" dans spring-servlet.xml
Rakesh Waghela
4
Rakesh Waghela a raison. Sans cet attribut, les beans Controller seront créés deux fois. Premièrement dans appContext et deuxièmement dans servletContext
UltraMaster
12

En termes simples,

applicationContext.xmldéfinit les beans partagés entre toutes les servlets. Si votre application possède plusieurs servlets, la définition des ressources communes dans le applicationContext.xmlserait plus logique.

spring-servlet.xmldéfinit les beans associés uniquement à cette servlet. Ici, c'est le servlet du répartiteur. Ainsi, vos contrôleurs Spring MVC doivent être définis dans ce fichier.

Il n'y a rien de mal à définir tous les beans dans le spring-servlet.xmlsi vous exécutez un seul servlet dans votre application Web.

Krishna
la source
3
Je peux définir tous les beans dans spring-servlet.xml, mais il devrait également y avoir applicationContext.xml qui peut être vide (sans beans) dans ce cas. Correct?
Mikhail Kopylov
6

Dans la technologie des servlets, si vous souhaitez transmettre une entrée à un servlet particulier, vous devez passer les paramètres init comme le code ci-dessous.

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

Si vous souhaitez passer des entrées communes à toutes les servlets, vous devez alors configurer le paramètre de contexte. Exemple

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

Tellement exactement comme cela lorsque nous travaillons avec Spring MVC, nous devons fournir des informations au servlet prédéfini fourni par Spring, qui est DispatcherServlet via init param. La configuration est donc en jachère, nous fournissons ici le paramètre spring-servlet.xml en tant que paramètre init à 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_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>

Encore une fois, nous avons besoin d'un paramètre de contexte. Cela s'applique à toute l'application. Nous pouvons donc fournir le contexte racine qui est applicationcontext.xml La configuration est la suivante:

    <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
la source
4

Les contextes d'application fournissent un moyen de résoudre les messages texte, notamment la prise en charge de i18n de ces messages. Les contextes d'application fournissent un moyen générique de charger des ressources de fichiers, telles que des images. Les contextes d'application peuvent publier des événements sur des beans enregistrés comme écouteurs. Certaines opérations sur le conteneur ou les beans du conteneur, qui doivent être gérées de manière programmatique avec une fabrique de beans, peuvent être gérées de manière déclarative dans un contexte d'application. Prise en charge de ResourceLoader: l'interface des ressources de Spring nous fournit une abstraction générique flexible pour gérer les ressources de bas niveau. Un contexte d'application lui-même est un ResourceLoader, donc fournit une application avec accès aux instances de ressources spécifiques au déploiement. Prise en charge de MessageSource: le contexte d'application implémente MessageSource, une interface utilisée pour obtenir des messages localisés,

Sujata
la source