web-dev-qa-db-fra.com

Comment les mappages d'URL Servlet dans web.xml sont-ils utilisés?

J'ai un fichier web.xml avec du contenu:

<servlet>
    <servlet-name>servlet1</servlet-name>
    <servlet-class>org.mycompany.test1</servlet-class>
</servlet>
<servlet>
    <servlet-name>servlet2</servlet-name>
    <servlet-class>org.mycompany.test2</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>servlet1</servlet-name>
    <url-pattern>/path/test</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>servlet2</servlet-name>
    <url-pattern>/path/test/*</url-pattern>
</servlet-mapping>

J'ai essayé les demandes

.../path/test/abc 
.../path/test

Les deux demandes sont traitées par Servlet2. Pourquoi?

MISE À JOUR

Merci les gars pour votre aide. J'ai réalisé que le comportement dépend de l'ordre de déclaration de mappage de servlet. J'ai essayé ce web.xml

<servlet>
    <servlet-name>servlet1</servlet-name>
    <servlet-class>org.mycompany.test1</servlet-class>
</servlet>
<servlet>
    <servlet-name>servlet2</servlet-name>
    <servlet-class>org.mycompany.test2</servlet-class>
</servlet>
<servlet>
    <servlet-name>servlet3</servlet-name>
    <servlet-class>org.mycompany.test3</servlet-class>
</servlet>
<servlet>
    <servlet-name>servlet4</servlet-name>
    <servlet-class>org.mycompany.test4</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>servlet1</servlet-name>
    <url-pattern>/path/test</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>servlet2</servlet-name>
    <url-pattern>/path/test/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>servlet3</servlet-name>
    <url-pattern>/path/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>servlet4</servlet-name>
    <url-pattern>/path</url-pattern>
</servlet-mapping>

résultats:

.../path/test/abc - servlet2
.../path/test/ - servlet2
.../path/test - servlet2

.../path/abc - servlet3
.../path/ - servlet4
.../path - servlet4
22
wfr

À partir de Servlet 3.0 spécification , voici comment le conteneur Web doit localiser le servlet après avoir reçu une demande (c'est moi qui souligne):

Le chemin utilisé pour le mappage vers un servlet est l'URL de demande de l'objet de demande moins le chemin de contexte et les paramètres de chemin. Les règles de mappage de chemin URL ci-dessous sont utilisées dans l'ordre. La première correspondance réussie est utilisée sans aucune autre tentative de correspondance :

  1. Le conteneur essaiera de trouver une correspondance exacte du chemin de la demande avec le chemin du servlet. Une correspondance réussie sélectionne le servlet.
  2. Le conteneur essaiera récursivement de faire correspondre le préfixe de chemin le plus long. Pour ce faire, descendez l’arborescence des chemins un répertoire à la fois, en utilisant le caractère ‘/’ comme séparateur de chemin. La correspondance la plus longue détermine la servlet sélectionnée.
  3. Si le dernier segment du chemin URL contient une extension (par exemple .jsp), le conteneur de servlet essaiera de faire correspondre un servlet qui gère les demandes d'extension. Une extension est définie comme la partie du dernier segment après le dernier caractère ".".
  4. Si aucune des trois règles précédentes n'entraîne une correspondance de servlet, le conteneur tentera de diffuser le contenu approprié pour la ressource demandée. Si un servlet "par défaut" est défini pour l'application, il sera utilisé. De nombreux conteneurs fournissent un servlet implicite par défaut pour servir le contenu.

Le conteneur doit utiliser des comparaisons de chaînes sensibles à la casse pour la correspondance.

Vous devriez également regarder la spécification des mappages (donnée ci-dessous):

Dans le descripteur de déploiement d'application Web, la syntaxe suivante est utilisée pour définir les mappages:

  • Une chaîne commençant par un ‘/’ caractère et se terminant par un ‘/*’ le suffixe est utilisé pour le mappage des chemins.

  • Une chaîne commençant par un ‘*.’ le préfixe est utilisé comme mappage d'extension.

  • La chaîne vide ("") est un modèle d'URL spécial qui correspond exactement à la racine de contexte de l'application, c'est-à-dire aux demandes du formulaire http://Host:port/<contextroot>/. Dans ce cas, les informations sur le chemin sont ’/’ et le chemin du servlet et le chemin du contexte est une chaîne vide (““).

  • Une chaîne contenant uniquement le ’/’ le caractère indique le servlet "par défaut" de l'application. Dans ce cas, le chemin du servlet est l'URI de la demande moins le chemin du contexte et les informations sur le chemin sont nulles.

  • Toutes les autres chaînes sont utilisées uniquement pour les correspondances exactes

Voyons maintenant des exemples. Considérez l'ensemble de mappages suivant:

 Modèle de chemin Servlet 
/Foo/bar/* servlet1 
/Baz/* servlet2 
/Catalogue servlet3 
 *. Bop servlet4 

Le comportement suivant en résulterait:

 Demande de gestion de servlet de chemin entrant 
/Foo/bar/index.html servlet1 
/Foo/bar/index.bop servlet1 
/Baz servlet2 
 /baz/index.html servlet2 
/catalog servlet3 
/catalog/index.html servlet "par défaut" 
/catalog/racecar.bop servlet4 
/index .bop servlet4 

Notez que dans le cas de /catalog/index.html et /catalog/racecar.bop, le servlet mappé sur “/catalog” n'est pas utilisé car la correspondance n'est pas exacte.

Venons-en maintenant à votre problème :)

/path/test appartient au 5ème point de spécification des mappages. Ce qui signifie que seuls les chemins se terminant par /path/test ciblera servlet1.

Toutefois /path/test/* se qualifie pour le premier point de la même spécification. Cela signifie que:

.../path/test sera géré par servlet1 et

.../path/test/abc sera géré par servlet2

Ce qui a été vérifié par moi dans une application de test.

49
Nishant Shreshth

Vos chemins sont en conflit.

Vos deux chemins signifient la même chose, le '/ *' ne fait aucune différence. Apparemment, lorsque vous essayez votre chemin, la dernière correspondance (servlet2) est exécutée.

Vous mettez généralement un chemin avec le nom du servlet, comme par exemple:

/path/test/servlet1
/path/test/servlet2
1
Terry