Différence entre / et / * dans le modèle d’URL de mappage de servlet

Le code familier:

 main /*   main /  

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

Qu’en est-il / ? Il ne correspond certainement pas à http://host:port/context racine de http://host:port/context uniquement. En fait, il acceptera http://host:port/context/hello , mais rejettera http://host:port/context/hello.jsp .

Quelqu’un peut-il expliquer comment http://host:port/context/hello mappé?

    /*

    Le /* sur un servlet remplace 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 se retrouvera dans cette servlet. C’est donc un mauvais modèle d’URL pour les servlets. Généralement, vous souhaitez utiliser /* sur un Filter uniquement. Il est capable de laisser la requête continuer vers n’importe quelle servlet en écoutant un motif d’URL plus spécifique en appelant FilterChain#doFilter() .

    /

    Le / ne remplace aucun autre servlet. Il ne remplace que le servlet par défaut du servletcontainer pour toutes les requêtes qui ne correspondent à aucun autre servlet enregistré. Ceci est normalement invoqué uniquement sur les ressources statiques (CSS / JS / image / etc) et les listes de répertoires. Le servlet par défaut du servletcontainer est également capable de traiter les requêtes de cache HTTP, le streaming multimédia (audio / vidéo) et les CV de téléchargement de fichiers. Habituellement, vous ne voulez pas remplacer le servlet par défaut car vous devriez vous occuper de toutes ses tâches, ce qui n’est pas vraiment sortingvial (la bibliothèque d’utilitaires JSF OmniFaces a un exemple open source ). C’est aussi un mauvais modèle d’URL pour les servlets. Pour ce qui est de savoir pourquoi les pages JSP ne touchent pas ce servlet, c’est parce que le servlet JSP intégré au conteneur de servlet sera invoqué, qui est déjà mappé par défaut sur le modèle d’URL plus spécifique *.jsp .

    Ensuite, il y a aussi le modèle d’URL de chaîne vide . Ceci sera invoqué lorsque la racine de contexte est demandée. Cela diffère de l’approche qui n’est pas appelée lorsqu’un sous-dossier est demandé. C’est probablement le modèle d’URL que vous recherchez en cas de besoin d’un ” servlet de page d’accueil “. Je dois seulement admettre que je m’attendais intuitivement au modèle d’URL de chaîne vide et le slash URL pattern / être défini exactement l’inverse, donc je peux comprendre que beaucoup de starters ont été confus à ce sujet. Mais c’est ce que c’est.

    Contrôleur frontal

    Si vous avez réellement l’ intention d’avoir un servlet de contrôleur frontal, vous devriez le mapper sur un modèle d’URL plus spécifique comme *.html , *.do , /pages/* , /app/* , etc. Vous pouvez vous cacher le modèle d’URL du contrôleur frontal et les ressources statiques sur un modèle d’URL commun tel que /resources/* , /static/* , etc. à l’aide d’un filtre de servlet. Voir aussi Comment empêcher les ressources statiques d’être traitées par le servlet du contrôleur frontal mappé sur / * . Il convient de noter que Spring MVC a un servlet de ressource statique intégré, c’est pourquoi vous pouvez mapper son contrôleur frontal sur / si vous configurez un modèle d’URL commun pour les ressources statiques au spring. Voir aussi Comment gérer le contenu statique dans Spring MVC?

    J’aimerais compléter la réponse de BalusC par les règles de cartographie et un exemple.

    Règles de mappage de la spécification Servlet 2.5:

    1. URL exacte de la carte
    2. Chemins génériques de carte
    3. Extensions de carte
    4. Mapper sur le servlet par défaut

    Dans notre exemple, il y a trois servlets. / est le servlet par défaut installé par nous. Tomcat installe deux servlets pour servir jsp et jspx. Donc, pour mapper http://host:port/context/hello

    1. Pas de servlets d’URL exacts installés, ensuite.
    2. Pas de servlets de chemins d’access génériques installés, ensuite.
    3. Ne correspond à aucune extension, ensuite.
    4. Mappez sur le servlet par défaut, revenez.

    Pour mapper http://host:port/context/hello.jsp

    1. Pas de servlets d’URL exacts installés, ensuite.
    2. Pas de servlets de chemins d’access génériques installés, ensuite.
    3. Servlet d’extension trouvé, retour.

    Peut-être avez-vous besoin de savoir comment les URL sont également mappées, car j’ai souffert de 404 heures pendant des heures. Il existe deux types de gestionnaires gérant 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 que Spring n’utilisera pas le chemin complet pour mapper une URL vers un contrôleur. Qu’est-ce que ça veut dire? Cela signifie que lorsque vous définissez un servlet-mapping :

      viewServlet /perfix/*  

    le gestionnaire utilisera effectivement la partie * pour trouver le contrôleur. Par exemple, le contrôleur suivant rencontrera 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 Ssortingng doSomething(HttpServletRequest request) { .... } } 

    C’est un match parfait, non? Mais pourquoi 404 . Comme mentionné précédemment, la valeur par défaut de alwaysUseFullPath est false, ce qui signifie que dans votre requête, seul /api/feature/doSomething est utilisée pour trouver un contrôleur correspondant, mais aucun contrôleur ne se soucie de ce chemin. Vous devez soit changer votre URL en /perfix/perfix/api/feature/doSomething soit supprimer perfix de la base @RequestingMapping .

    Je pense que la réponse de Candy est la plupart du temps correcte. Je pense qu’il y a une petite partie.

    Pour mapper l’hôte: port / context / hello.jsp

    1. Pas de servlets d’URL exacts installés, ensuite.
    2. Servlets de chemins d’access génériques trouvés , retour.

    Je crois que pourquoi “/ *” ne correspond pas à host: port / context / hello car il traite “/ hello” comme un chemin plutôt que comme un fichier (car il n’a pas d’extension).

    La différence essentielle entre /* et / est qu’une servlet avec mapping /* sera sélectionnée avant toute servlet avec un mapping d’extension (comme *.html ), tandis qu’une servlet avec mapping / sera sélectionnée uniquement après l’étude des mappages d’extension (et sera utilisé pour toute demande qui ne correspond à rien d’autre – c’est le “servlet par défaut”.

    En particulier, un mappage /* sera toujours sélectionné avant un / mapping. Avoir soit empêché les demandes d’atteindre le servlet par défaut du conteneur.

    L’un ou l’autre sera sélectionné uniquement après les mappages de servlets qui sont des correspondances exactes (comme /foo/bar ) et ceux qui sont des mappages de chemins plus longs que /* (comme /foo/* ). Notez que le mappage de chaîne vide correspond exactement à la racine du contexte ( http://host:port/context/ ).

    Voir le chapitre 12 de la spécification de servlet Java, disponible dans la version 3.1 à l’ adresse http://download.oracle.com/otndocs/jcp/servlet-3_1-fr-eval-spec/index.html .