Comment sont servlet url mappings dans le web.xml utilisé?

j'ai une toile.fichier xml avec 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 requêtes 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 servlet-mapping déclaration. J'ai essayé ce site 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
21
demandé sur Sotirios Delimanolis 2013-03-13 16:38:19

2 réponses

De Servlet 3.0 cahier des charges , c'est comment le conteneur web doit localiser la servlet après la réception d'une demande (l'emphase est mienne):

le chemin utilisé pour la mise en correspondance vers un servlet est L'URL de la requête objet demande moins le chemin de contexte et le chemin de paramètres. Le Les règles de mappage de chemin D'URL ci-dessous sont utilisées dans l'ordre. le premier succès la correspondance est utilisée sans autre correspondance tentée :

  1. le conteneur tentera de trouver une correspondance exacte du chemin de la requête au chemin du servlet. Un match réussi sélectionne le servlet.
  2. le conteneur tentera de façon récursive de correspondre au plus long chemin-préfixe. Ceci est fait en descendant l'arbre de chemin un répertoire à un moment, en utilisant le caractère ’/’ comme séparateur de chemin. La plus longue match détermine le servlet sélectionné.
  3. si le dernier segment du chemin de L'URL contient une extension (par exemple .jsp), le container de servlet va essayer de correspondre à un servlet qui manipule les demandes de prolongation. Une extension est définie comme la partie de le dernier segment après le dernier".’ caractère.
  4. si aucune des trois règles précédentes n'aboutit à une correspondance de servlet, le conteneur tentera de servir un contenu approprié pour ressources demandées. Si un "défaut" servlet est défini pour le de l'application, il sera utilisé. De nombreux conteneurs fournissent une servlet par défaut pour servir le contenu.

le conteneur doit utiliser des comparaisons de chaînes de caractères sensibles à la casse pour l'appariement.

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

dans le descripteur de déploiement de L'application Web, la syntaxe suivante est utilisé pour définir mappings:

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

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

  • la chaîne vide ("") est un patron D'URL spécial qui correspond exactement à la racine du contexte de l'application, c'est à dire, les demandes de la forme http://host:port/<contextroot>/ . Dans ce cas, l'information de chemin est ’/’ et le chemin de servlet et le chemin de contexte sont des chaînes vides (““) .

  • une chaîne contenant seulement le caractère ’/’ indique le " défaut" servlet de l'application. Dans ce cas, le chemin de servlet est URI de la requête moins le chemin de contexte et les informations de chemin sont nulles.

  • toutes autres les chaînes sont utilisées pour les correspondances exactes seulement

voyons maintenant des exemples. Considérons l'ensemble suivant de mappings:

Path Pattern            Servlet
/foo/bar/*              servlet1
/baz/*                  servlet2
/catalog                servlet3
*.bop                   servlet4

le comportement suivant résulterait:

Incoming Path           Servlet Handling Request
/foo/bar/index.html     servlet1
/foo/bar/index.bop      servlet1
/baz                    servlet2
/baz/index.html         servlet2
/catalog                servlet3
/catalog/index.html     “default” servlet
/catalog/racecar.bop    servlet4
/index.bop              servlet4

noter que dans le cas de /catalog/index.html et /catalog/racecar.bop , le servlet mappée à “/catalog” n'est pas utilisé parce que le match n'est pas exact.

maintenant à venir à votre problème :)

/path/test fait partie du cinquième point de spécification des correspondances. Ce qui signifie que seuls les chemins se terminant par /path/test cibleront servlet1 .

toutefois, /path/test/* est admissible au premier point de la même spécification. Cela signifie que:

.../path/test sera traité par servlet1 et

.../path/test/abc sera traité par servlet2

qui a été vérifié par moi dans une application d'essai.

46
répondu Nishant Shreshth 2013-03-13 17:46:12

vos chemins sont en conflit.

les 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 habituellement un chemin avec le nom de Servlet, comme par exemple:

/path/test/servlet1
/path/test/servlet2
1
répondu Terry 2013-03-13 13:28:23