Différence entre / et / * dans le modèle d'url de mapping de servlet

le code familier:

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

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

je crois comprendre que /* correspond à http://host:port/context/* .

et / ? Il ne correspond pas seulement à la racine http://host:port/context . En fait , elle acceptera http://host:port/context/hello , mais rejettera http://host:port/context/hello.jsp .

est-ce que quelqu'un peut expliquer comment http://host:port/context/hello est cartographié?

156
demandé sur BalusC 2010-11-10 04:28:38

5 réponses

<url-pattern>/*</url-pattern>

le /* sur un servlet l'emporte sur tous les autres servlets, y compris tous les servlets fournis par le servletcontainer tels que le servlet par défaut et le servlet JSP. Quelle que soit votre requête, elle finira dans ce servlet. C'est donc un mauvais motif D'URL pour les servlets. Généralement, vous souhaitez utiliser /* sur un Filter . Il est capable de laisser la requête continuer vers n'importe lequel des servlets écoutant sur un modèle D'URL plus spécifique en appelant FilterChain#doFilter() .

<url-pattern>/</url-pattern>

le / ne remplace aucun autre servlet. Il remplace seulement le servlet par défaut du servletcontainer pour toutes les requêtes qui ne correspondent à aucun autre servlet enregistré. Ceci n'est normalement invoqué que sur les ressources statiques (CSS/JS/image/etc) et les répertoires. Le servlet par défaut du servletcontainer est également capable de traitement des requêtes de cache HTTP, de streaming de médias (audio/vidéo) et des reprises de téléchargement de fichiers. Habituellement, vous ne voulez pas surcharger le servlet par défaut car vous auriez autrement à prendre soin de toutes ses tâches, qui n'est pas exactement trivial (bibliothèque d'utilité JSF OmniFaces a un open source exemple ). C'est donc aussi un mauvais motif D'URL pour les servlets. Quant à savoir pourquoi les pages JSP n'atteignent pas ce servlet, c'est parce que le le servlet JSP intégré par servletcontainer sera invoqué, qui est déjà par défaut mappé sur le modèle D'URL plus spécifique *.jsp .

<url-pattern></url-pattern>

puis il y a aussi l'approche . This will be invoked when the context root is requested. This is different from the <welcome-file> qui n'est pas invoquée lorsqu'un sous-dossier est demandé. C'est très probablement le modèle D'URL que vous recherchez réellement dans le cas où vous voulez un " servlet de page d'accueil ". Je n'ai qu'à admettez que je m'attendrais intuitivement à ce que le motif D'URL de chaîne vide et le motif D'URL de barre oblique / soit défini exactement dans l'autre sens, donc je peux comprendre que beaucoup de démarreurs se sont confondus sur ce point. Mais elle est ce qu'elle est.

Contrôleur Avant

dans le cas où vous en fait avoir l'intention d'avoir un servlet contrôleur frontal, alors vous feriez mieux de le mapper sur un modèle D'URL plus spécifique comme *.html , *.do , /pages/* , /app/* , etc. Vous pouvez cacher le modèle D'URL du contrôleur frontal et couvrir les ressources statiques sur un modèle D'URL commun comme /resources/* , /static/* , etc à l'aide d'un filtre de servlet. Voir aussi comment empêcher les ressources statiques d'être manipulées par le servlet du contrôleur front qui est mappé sur /* . Noté devrait être que le ressort MVC a un servlet de ressource statique intégré, donc c'est pourquoi vous pourriez mapper son contrôleur avant sur / si vous configurez un modèle D'URL commun pour les ressources statiques au printemps. Voir aussi comment gérer le contenu statique en MVC de printemps?

231
répondu BalusC 2017-05-23 11:55:09

j'aimerais compléter la réponse de BalusC avec les règles de mappage et un exemple.

règles de Mappage de Servlet 2.5 spécifications:

  1. Carte exacte URL
  2. Carte joker chemins
  3. extensions de carte
  4. Carte à la valeur par défaut de la servlet

dans notre exemple, il y a trois servlets. / est le servlet par défaut que nous avons installé. Tomcat installe deux servlets pour servir jsp et jspx. Ainsi à la carte http://host:port/context/hello

  1. Aucune adresse URL exacte de servlets installé, à côté.
  2. Pas de générique chemins de servlets installé, à côté.
  3. ne correspond à aucune extension, suivant.
  4. Carte à la valeur par défaut de la servlet, retour.

à la carte http://host:port/context/hello.jsp

  1. Aucune adresse URL exacte de servlets installé, à côté.
  2. Pas de générique chemins de servlets installé, à côté.
  3. trouvé servlet d'extension, retour.
40
répondu Candy Chiu 2014-11-29 16:12:23

peut-être avez-vous besoin de savoir comment les urls sont mappées aussi, puisque j'ai souffert 404 pendant des heures. Il existe deux types de manipulateurs qui traitent les demandes. BeanNameUrlHandlerMapping et SimpleUrlHandlerMapping . Lorsque nous avons défini un servlet-mapping , nous utilisons SimpleUrlHandlerMapping . Une chose que nous devons savoir est que ces deux gestionnaires partagent une propriété commune appelée alwaysUseFullPath qui est par défaut à false .

false signifie ici que Spring n'utilisera pas le chemin complet pour mapper une url vers un controller. Ça veut dire quoi? Cela signifie que lorsque vous définissez un servlet-mapping :

<servlet-mapping>
    <servlet-name>viewServlet</servlet-name>
    <url-pattern>/perfix/*</url-pattern>
</servlet-mapping>

le gestionnaire utilisera en fait le * pour trouver le contrôleur. Par exemple, le contrôleur suivant fera face à une erreur 404 lorsque vous le demanderez en utilisant /perfix/api/feature/doSomething

@Controller()
@RequestMapping("/perfix/api/feature")
public class MyController {
    @RequestMapping(value = "/doSomething", method = RequestMethod.GET) 
    @ResponseBody
    public String doSomething(HttpServletRequest request) {
        ....
    }
}

c'est une correspondance parfaite, non? Mais pourquoi 404 . Comme mentionné précédemment, la valeur par défaut de alwaysUseFullPath est false, ce qui signifie dans votre demande, /api/feature/doSomething est utilisé pour trouver un contrôleur correspondant, mais aucun contrôleur ne se soucie de ce chemin. Vous devez changer votre url en /perfix/perfix/api/feature/doSomething ou supprimer perfix de la base de MyController @RequestingMapping .

18
répondu hakunami 2015-10-23 02:52:59

je pense que la réponse de Candy est correcte. Il y a une petite partie que je pense autrement.

À la carte d'hôte:port/contexte/bonjour.jsp

  1. Aucune adresse URL exacte de servlets installé, à côté.
  2. chemin de remplacement trouvé servlets , retour.

je crois que pourquoi "/ * "ne correspond pas à host: port / context / hello parce qu'il traite "/ hello" comme un chemin au lieu d'un fichier (puisqu'il ne possède pas d'extension).

7
répondu hehe 2014-11-14 09:41:43

la différence essentielle entre /* et / est qu'un servlet avec mapping /* sera sélectionné avant tout servlet avec mapping d'extension (comme *.html ), alors qu'un servlet avec mapping / ne sera sélectionné qu'après que les mappings d'extension seront considérés (et sera utilisé pour toute requête qui ne correspond à rien d'autre---c'est le"servlet par défaut").

en particulier, un /* cartographie sera toujours sélectionné avant un mapping / . Avoir l'un ou l'autre empêche toute requête d'atteindre le propre servlet par défaut du conteneur.

sera sélectionné seulement après des mappages de servlet qui sont des Correspondances exactes (comme /foo/bar ) et ceux qui sont des mappages de chemin plus long que /* (comme /foo/* ). Notez que la correspondance des chaînes vides correspond exactement à la racine du contexte ( http://host:port/context/ ).

voir Chapitre 12 du Java Servlet Spécification, disponible dans la version 3.1 à http://download.oracle.com/otndocs/jcp/servlet-3_1-fr-eval-spec/index.html .

0
répondu Robert Tupelo-Schneck 2017-07-27 20:49:00