web-dev-qa-db-fra.com

Spring: nomsit vs contexteConfigLocation paramètres init dans web.xml

Je suis en train de lire la documentation de Spring MVC et j'ai une question concernant les paramètres init. J'utilise Spring 3.2 si c'est important. Quelle est la différence entre contextConfigLocation et namespace? ContextConfigLocation sert-il uniquement à spécifier les dossiers dans lesquels la classe de contexte peut trouver une définition XML et que l'attribut d'espace de nom est destiné à spécifier le nom du fichier?

<servlet>
        <servlet-name>AppServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>WEB-INF</param-value>
        </init-param>
        <init-param>
            <param-name>namespace</param-name>
            <param-value>application-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

Est-ce correct? Devrait-il utiliser /WEB-INF/application-context.xml? Et devriez-vous spécifier des chemins?

56
LuckyLuke

TL; DR

Il suffit de définir la (les) valeur (s) pour contextConfigLocation chaque fois que vous devez spécifier des fichiers de configuration personnalisés. De cette façon, vous spécifierez les noms de fichier de configuration et leurs emplacements.

Le namespace est essentiellement une autre manière de dire à la classe du chargeur de contexte de conteneur Spring quel fichier de configuration utiliser. Je ne m'en préoccupe jamais, mais j'utilise contextConfigLocation chaque fois que j'ai besoin de configurer des fichiers de configuration personnalisés.

Voici un exemple de l'un de mes précédents projets Spring (certaines configurations ont été omises pour des raisons de brièveté):

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://Java.Sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://Java.Sun.com/xml/ns/javaee
                            http://Java.Sun.com/xml/ns/javaee/web-app_3_0.xsd">

    <display-name>Spring Web Application example</display-name>

    <!-- Configurations for the root application context (parent context) -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring/jdbc/spring-jdbc.xml
            /WEB-INF/spring/security/spring-security-context.xml
        </param-value>
    </context-param>

    <!-- Configurations for the DispatcherServlet application context (child context) -->
    <servlet>
        <servlet-name>spring-mvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>
                /WEB-INF/spring/mvc/spring-mvc-servlet.xml
            </param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>spring-mvc</servlet-name>
        <url-pattern>/admin/*</url-pattern>
    </servlet-mapping>

</web-app>

Longue réponse

OK, voyons d'abord quelques moments importants. Nous traitons deux types de contextes:

  1. contexte racine (parent)
  2. contexte de servlet individuel (enfant)

Extrait de l’API Spring Framework (version 3.2.2 au moment de l’écriture) pour le WebApplicationContext (emphase mienne):

Comme les contextes d'application génériques, les contextes d'application Web sont hiérarchiques. Il existe un seul contexte racine par application, tandis que chaque servlet de l'application (y compris une servlet de répartition dans le framework MVC) possède son propre contexte enfant .

Aussi ici: hiérarchies de contexte :

Par exemple, si vous développez une application Web Spring MVC, vous aurez généralement un WebApplicationContext racine chargé via Spring ContextLoaderListener et un enfant WebApplicationContext chargé via le DispatcherServlet de Spring . Il en résulte une hiérarchie de contexte parent-enfant dans laquelle les composants partagés et la configuration d'infrastructure sont déclarés dans le contexte racine et utilisés dans le contexte enfant par des composants spécifiques au Web.

Et ici: 17.2 The DispatcherServlet :

Les instances de ApplicationContext dans Spring peuvent être étendues. Dans la structure Web MVC, chaque DispatcherServlet a son propre WebApplicationContext, qui hérite de tous les beans déjà définis dans la racine WebApplicationContext . Ces beans hérités peuvent être remplacés dans l'étendue spécifique à la servlet et vous pouvez définir de nouveaux beans spécifiques à l'étendue locale pour une instance de servlet donnée.


Voyons maintenant la configuration du contexte d'application racine . Voici un exemple:
web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://Java.Sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://Java.Sun.com/xml/ns/javaee
                            http://Java.Sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring/daoContext.xml
            /WEB-INF/spring/applicationContext.xml
        </param-value>
    </context-param>
</web-app>


D'après la documentation officielle du printemps (souligné par moi):
5.14.4 Instanciation commode ApplicationContext pour les applications Web :

Vous pouvez créer des instances ApplicationContext de manière déclarative en utilisant, par exemple, un ContextLoader. Bien sûr, vous pouvez également créer des instances ApplicationContext par programme à l'aide de l'une des implémentations ApplicationContext.

Vous pouvez enregistrer un ApplicationContext à l'aide de ContextLoaderListener (voir l'exemple ci-dessus).

L'écouteur inspecte le paramètre contextConfigLocation. Si le paramètre n'existe pas, le programme d'écoute utilise /WEB-INF/applicationContext.xml par défaut . Lorsque le paramètre existe, l'écouteur sépare la chaîne à l'aide de délimiteurs prédéfinis (virgule, point-virgule et espace) et utilise les valeurs comme emplacements où les contextes d'application seront recherchés. Les modèles de chemin d'accès de style Ant sont également pris en charge. Exemples: /WEB-INF/*Context.xml pour tous les fichiers dont le nom se termine par "Context.xml", situés dans le répertoire "WEB-INF", et /WEB-INF/**/*Context.xml pour tous. tels fichiers dans n’importe quel sous-répertoire de "WEB-INF".


Assez souvent, la configuration de Spring est répartie sur plusieurs fichiers. C'est plus logique et pratique, surtout dans les projets à grande échelle. Dans notre exemple, nous avons explicitement défini deux fichiers XML de configuration: daoContext.xml et applicationContext.xml à l'emplacement personnalisé: /WEB-INF/spring/. Encore une fois, si nous n'avions pas défini contextConfigLocation, le ContextLoaderListener essaierait de localiser le fichier de configuration par défaut: /WEB-INF/applicationContext.xml.

REMARQUE:
Le contexte racine est facultatif . Voir aussi cette réponse: https://stackoverflow.com/a/7451389/814702

Donc, si la valeur par défaut /WEB-INF/applicationContext.xml Le fichier de configuration ne répond pas à vos besoins, utilisez ContextLoaderListener avec <context-param> contextConfigLocation où vous pouvez définir un ou plusieurs fichiers de configuration personnalisés afin de définir le contexte de l'application racine .


Voyons maintenant le contexte d'application individuel (enfant) . De la documentation officielle du printemps (souligné par moi):
17.2 The DispatcherServlet

Lors de l'initialisation d'un DispatcherServlet, Spring MVC recherche un fichier nommé
[nom-servlet] -servlet.xml dans le répertoire WEB-INF
de votre application Web et crée les beans définis à cet emplacement, en remplaçant les définitions de tous les beans définis avec le même nom dans la portée globale.

Prenez en compte la configuration de servlet DispatcherServlet suivante (dans le fichier web.xml):

<web-app>

    <servlet>
        <servlet-name>golfing</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>golfing</servlet-name>
        <url-pattern>/golfing/*</url-pattern>
    </servlet-mapping>

</web-app>


A propos de contextConfigLocation et de l'espace de noms

De la documentation (c'est moi qui souligne):

Avec la configuration de Servlet ci-dessus en place, vous aurez besoin d’un fichier appelé
/WEB-INF/golfing-servlet.xml dans votre application; ce fichier contiendra tous vos composants (beans) spécifiques à Spring Web MVC. Vous pouvez modifier l'emplacement exact de ce fichier de configuration via un paramètre d'initialisation Servlet (voir ci-dessous pour plus de détails).
...
Vous pouvez personnaliser des instances individuelles de DispatcherServlet en ajoutant des paramètres d'initialisation de servlet (éléments init-param) à la déclaration de servlet dans le fichier web.xml. . Voir le tableau suivant pour la liste des paramètres pris en charge.

  • contextClass: Classe qui implémente WebApplicationContext, qui instancie le contexte utilisé par ce servlet. Par défaut, XmlWebApplicationContext est utilisé.

  • contextConfigLocation: Chaîne transmise à l'instance de contexte (spécifiée par contextClass) pour indiquer où le ou les contextes peuvent être trouvé. La chaîne consiste potentiellement en plusieurs chaînes (utilisant une virgule comme délimiteur) pour prendre en charge plusieurs contextes. Dans le cas de plusieurs emplacements de contexte avec des beans définis deux fois, l'emplacement le plus récent est prioritaire.

  • namespace: Espace de noms du WebApplicationContext. La valeur par défaut est [nom-servlet] -servlet.


Examinons maintenant la documentation de l'API pour les classes associées. La classe DispatcherServlet étend la classe abstraite FrameworkServlet . De la FrameworkServlet Documentation de l'API (emphase mienne):

Passe un init-param de servlet "contextConfigLocation" à l'occurrence de contexte, en l'analysant dans plusieurs chemins de fichiers potentiellement séparables par un nombre quelconque de virgules et d'espaces, comme
"test-servlet.xml, myServlet.xml". S'il n'est pas spécifié explicitement, l'implémentation de contexte est supposée créer un emplacement par défaut à partir de l'espace de noms du servlet .

L'espace de nom par défaut est "'servlet-name'-servlet", par exemple. "test-servlet" pour un nom de servlet "test" (menant à un emplacement par défaut "/WEB-INF/test-servlet.xml" avec XmlWebApplicationContext). L'espace de noms peut également être défini explicitement via le servlet "espaces de noms" init-param .

Voici l'extrait du code source FrameworkServlet:
FrameworkServlet.Java

....
/**
* Suffix for WebApplicationContext namespaces. If a servlet of this class is
* given the name "test" in a context, the namespace used by the servlet will
* resolve to "test-servlet".
*/
public static final String DEFAULT_NAMESPACE_SUFFIX = "-servlet";
....


La classe de contexte par défaut pour FrameworkServlet est XmlWebApplicationContext . De la XmlWebApplicationContext Documentation de l'API (emphase mienne):

Par défaut, la configuration sera issue de "/WEB-INF/applicationContext.xml" pour le contexte racine et de "/WEB-INF/test-servlet.xml" pour un contexte avec l'espace de noms "test-servlet" (comme pour une instance DispatcherServlet avec le nom de servlet "test").

Les valeurs par défaut de l'emplacement de configuration peuvent être remplacées via le paramètre de contexte "contextConfigLocation" de ContextLoader et le servlet init-param de FrameworkServlet . Les emplacements de configuration peuvent désigner des fichiers concrets tels que "/WEB-INF/context.xml" ou des modèles de style Ant tels que "/WEB-INF/*-context.xml" (voir la section javadoc de PathMatcher pour plus de détails sur les modèles).

Le remplacement des emplacements de configuration par défaut à l'aide de contextConfigLocation est identique à l'exemple ci-dessus pour le contexte d'application racine.

En ce qui concerne le remplaçant l'espace de noms par défaut , il y a des moments importants. Lorsque vous définissez un nouvel espace de noms, ne le préfixez pas avec /WEB-INF et ne pas ajouter .xml à elle . La raison de cela peut être découverte si nous cherchons dans le fichier source la classe XmlWebApplicationContext:
XmlWebApplicationContext.Java

...

/** Default config location for the root context */
public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";

/** Default prefix for building a config location for a namespace */
public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/";

/** Default suffix for building a config location for a namespace */
public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml";

...

/**
* The default location for the root context is "/WEB-INF/applicationContext.xml",
* and "/WEB-INF/test-servlet.xml" for a context with the namespace "test-servlet"
* (like for a DispatcherServlet instance with the servlet-name "test").
*/
@Override
protected String[] getDefaultConfigLocations() {
    if (getNamespace() != null) {
        return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() + DEFAULT_CONFIG_LOCATION_SUFFIX};
    }
    else {
        return new String[] {DEFAULT_CONFIG_LOCATION};
    }
}

Comme vous pouvez le constater, le code source dit tout.


Exemple de spécification d'un espace de noms personnalisé

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://Java.Sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://Java.Sun.com/xml/ns/javaee
                            http://Java.Sun.com/xml/ns/javaee/web-app_3_0.xsd">


    <!-- Configurations for the DispatcherServlet application context (child context) -->
    <servlet>
        <servlet-name>spring-mvc</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>namespace</param-name>
            <param-value>spring/mvc/spring-mvc</param-value>
        </init-param>
    </servlet>
    <servlet-mapping>
        <servlet-name>spring-mvc</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>

</web-app>

Le résultat est que, au lieu d'utiliser l'espace de noms par défaut pour construire le chemin d'accès au fichier de configuration, ce serait autrement /WEB-INF/spring-mvc-servlet.xml, le conteneur cherchera /WEB-INF/spring/mvc/spring-mvc.xml.

REMARQUE:
Les explications ci-dessus relatives à la configuration de l'espace de noms personnalisé concernent la classe par défaut XmlWebApplicationContext . On peut spécifier une classe alternative, comme AnnotationConfigWebApplicationContext , il y aura donc des moments spéciaux pour cela.


CONCLUSION

Il est beaucoup plus facile d'utiliser (IMHO) le paramètre contextConfigLocation pour définir des fichiers de configuration personnalisés, à la fois pour le contexte de l'application racine et pour les contextes individuels. La seule différence est que vous utilisez <context-param> dans les <web-app> élément, mais PAS dans un servlet spécifique (n'oubliez pas non plus la classe listener). Et pour le contexte enfant que vous utilisez <init-param> imbriqué dans le <servlet> élément pour chaque servlet spécifique . Voir mes exemples de configurations ( web.xml) au tout début de cet article.

Ressources supplémentaires (comme si ce qui précède n'était pas suffisant :-)):

167
informatik01

Je pense que la réponse de LuckyLuke contient de nombreuses informations utiles, mais elle ne répond pas à la question. En particulier, comment les paramètres "namespace" et "contextConfigLocation" fonctionnent-ils ensemble?

Le seul endroit où je pourrais trouver la réponse concrète est le code source:

  • namespace Paremeter définit un espace de noms personnalisé à utiliser pour la construction d'un valeur par défaut emplacement de configuration contextuelle.
  • Le paramètre contextConfigLocation définit explicitement l'emplacement de configuration du contexte, au lieu de s'appuyer sur l'emplacement par défaut construit à partir de l'espace de noms
4
Sava Jcript

Quelle est la différence entre contextConfigLocation et namespace? contextConfigLocation est utilisé pour spécifier le chemin des fichiers de configuration print, ce qui signifie qu'ils seront initialisés. namespace est utilisé pour spécifier le chemin d'accès et le nom du DispatcherServlet de Spring MVC. la valeur par défaut est [Dispatcher_name]-servlet.xml, Voici un exemple:

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>namespace</param-name>
        <param-value>config/spring-mvc</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

Spring recherchera un fichier à utiliser comme c'est mvc config par le chemin de /WEB-INF/config/spring-mvc.xml.
Est-ce que contextConfigLocation est uniquement destiné à spécifier les dossiers dans lesquels la classe de contexte peut trouver une définition XML

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/config/app-*.xml</param-value>
</context-param>

Le code ci-dessus a montré que, lorsque l'application démarrera, Spring chargera tous les fichiers dont le nom commence par 'app-' et se termine par '.xml' dans le répertoire WEB-INF/config.

Faut-il utiliser /WEB-INF/application-context.xml? Et devez-vous spécifier les chemins?
Grâce à l’exemple ci-dessus, nous pouvons savoir que lors de la configuration de Spring, nous devons spécifier le chemin complet et le nom du fichier générique, et lorsque SpringMVC uniquement, nous devons spécifier le chemin (s'il est situé dans un répertoire, n'incluez pas le nom WEB). Répertoire INF) et nom (ne pas inclure l’extension).
J'espère vous aider :)

3
Hunter Zhao