Puis-je exclure certaines URL concrètes de <url-pattern> dans <filter-mapping>?
127
Je veux qu'un filtre concret soit appliqué à toutes les URL sauf pour un béton (c'est-à-dire à l' /*exception de/specialpath ).
Y a-t-il une possibilité de le faire?
exemple de code:
<filter><filter-name>SomeFilter</filter-name><filter-class>org.somproject.AFilter</filter-class></filter><filter-mapping><filter-name>SomeFilter</filter-name><url-pattern>/*</url-pattern><!-- the question is: how to modify this line? --><dispatcher>REQUEST</dispatcher><dispatcher>FORWARD</dispatcher></filter-mapping>
L'API Servlet standard ne prend pas en charge cette fonctionnalité. Vous pouvez soit utiliser un filtre de réécriture d'URL pour cela comme celui de Tuckey (qui est très similaire à Apache HTTPD mod_rewrite), soit ajouter une vérification dans la doFilter()méthode d'écoute du filtre /*.
String path =((HttpServletRequest) request).getRequestURI();if(path.startsWith("/specialpath/")){
chain.doFilter(request, response);// Just continue chain.}else{// Do your business stuff here for all paths other than /specialpath.}
Vous pouvez si nécessaire spécifier les chemins à ignorer en tant que init-paramfiltre afin de pouvoir le contrôler de web.xmltoute façon. Vous pouvez l'obtenir dans le filtre comme suit:
Si le filtre fait partie de l'API tierce et que vous ne pouvez donc pas le modifier, mappez-le sur un filtre plus spécifique url-pattern, par exemple, /otherfilterpath/*et créez un nouveau filtre sur /*lequel redirige vers le chemin correspondant au filtre tiers.
Pour éviter que ce filtre ne s'appelle lui-même dans une boucle infinie, vous devez le laisser écouter (répartir) REQUESTuniquement et le filtre tiers FORWARDuniquement.
Mon problème est que le filtre n'est pas le mien, il provient de la bibliothèque de composants.
Roman
4
Ypu doit prendre le filtre de la bibliothèque compnent et l'étendre afin d'ajouter le code que vous souhaitez utiliser pour effectuer les exclusions.
gbtimmon
@BalusC Si le "/ specialpath" ne sert qu'une ressource statique comme js, css etc, est-ce que chain.doFilter () ralentit la réponse? Existe-t-il une méthode pour servir la ressource directement sans chaîner le filtre?
BenhurCD
@BenhurCD: Je n'ai vraiment aucune idée de comment vous pourriez résoudre ce problème de performance.
BalusC
13
J'ai utilisé une approche décrite par Eric Daugherty : j'ai créé un servlet spécial qui répond toujours avec du code 403 et mis son mapping avant le général.
Cette approche fonctionne lorsque vous souhaitez empêcher un certain filtre et tous les suivants. Cela devrait bien fonctionner si vous par exemple. souhaitez diffuser du contenu en tant que ressources statiques dans votre conteneur de servlet au lieu de laisser la logique de votre application (via un filtre comme GuiceFilter):
Mappez le dossier avec vos fichiers de ressources statiques au servlet par défaut. Créez un filtre de servlet et placez-le avant le GuiceFilter dans votre web.xml. Dans votre filtre créé, vous pouvez séparer le transfert de certaines demandes vers GuiceFilter et d'autres directement vers le répartiteur. L'exemple suit ...
Malheureusement, si vous souhaitez simplement sauter une seule étape dans la chaîne de filtres tout en conservant celles qui suivent, cela ne fonctionnera pas.
J'ai essayé d'aller avec votre solution, mais pour les fichiers que j'applique le filtre et brise la chaîne, j'obtiens l'erreur suivante; Exception non interceptée lancée par le filtre Filtre de ressources statiques: java.io.FileNotFoundException. Une idée pourquoi?
shamaleyte
Dans les configurations multi-contextes, l'utilisation .getRequestURI()sera interrompue (provoquant très probablement un 404) car .getRequestDispatcherelle se résout par rapport au chemin du contexte . Si votre chemin de contexte est /a, alors dans votre exemple, l'URI de la requête serait /a/static, et l'utilisation le getRequestDispatcher("/a/static")fera résoudre à la /a/a/staticplace. Correction: utilisez à la .getServletPath()place de .getRequestURI(). Je vais soumettre une modification pour résoudre ce problème, mais je voulais juste laisser un commentaire FYI
Reid
3
Je ne pense pas que vous le puissiez, la seule autre alternative de configuration est d'énumérer les chemins que vous souhaitez filtrer, donc au lieu de /*vous pouvez en ajouter pour /this/*et /that/*etc., mais cela ne conduira pas à une solution suffisante lorsque vous en avez beaucoup de ces chemins.
Ce que vous pouvez faire est d'ajouter un paramètre au filtre en fournissant une expression (comme une expression régulière) qui est utilisée pour ignorer la fonctionnalité de filtre pour les chemins correspondants. Le conteneur de servlet appellera toujours votre filtre pour ces URL, mais vous aurez un meilleur contrôle sur la configuration.
Éditer
Maintenant que vous mentionnez que vous n'avez aucun contrôle sur le filtre, vous pouvez soit hériter de l'appel de ce filtre super méthodes d' dans ses méthodes, sauf lorsque le chemin d'url que vous souhaitez ignorer est présent et de suivre la chaîne de filtres comme @BalusC proposé, soit de construire un filtre qui instancie votre filtre et délègue dans les mêmes circonstances. Dans les deux cas, les paramètres de filtre incluent à la fois le paramètre d'expression que vous ajoutez et ceux du filtre dont vous héritez ou auquel vous déléguez.
L'avantage de créer un filtre délégant (un wrapper) est que vous pouvez ajouter la classe de filtre du filtre enveloppé en tant que paramètre et la réutiliser dans d'autres situations comme celle-ci.
Si, pour une raison quelconque, vous ne pouvez pas modifier le mappage de filtre d'origine ("/ *" dans mon cas) et que vous envoyez vers un filtre tiers non modifiable, vous pouvez trouver utile ce qui suit:
Intercepter le chemin à contourner
Passer à et exécuter le dernier anneau de la chaîne de filtres (le servlet lui-même)
Le saut se fait par réflexion, en inspectant les instances de conteneur en mode débogage
J'ai utilisé une approche décrite par Eric Daugherty : j'ai créé un servlet spécial qui répond toujours avec du code 403 et mis son mapping avant le général.
Fragment de cartographie:
Et la classe servlet:
la source
Cette approche fonctionne lorsque vous souhaitez empêcher un certain filtre et tous les suivants. Cela devrait bien fonctionner si vous par exemple. souhaitez diffuser du contenu en tant que ressources statiques dans votre conteneur de servlet au lieu de laisser la logique de votre application (via un filtre comme GuiceFilter):
Mappez le dossier avec vos fichiers de ressources statiques au servlet par défaut. Créez un filtre de servlet et placez-le avant le GuiceFilter dans votre web.xml. Dans votre filtre créé, vous pouvez séparer le transfert de certaines demandes vers GuiceFilter et d'autres directement vers le répartiteur. L'exemple suit ...
web.xml
StaticResourceFilter.class
Malheureusement, si vous souhaitez simplement sauter une seule étape dans la chaîne de filtres tout en conservant celles qui suivent, cela ne fonctionnera pas.
la source
.getRequestURI()
sera interrompue (provoquant très probablement un 404) car.getRequestDispatcher
elle se résout par rapport au chemin du contexte . Si votre chemin de contexte est/a
, alors dans votre exemple, l'URI de la requête serait/a/static
, et l'utilisation legetRequestDispatcher("/a/static")
fera résoudre à la/a/a/static
place. Correction: utilisez à la.getServletPath()
place de.getRequestURI()
. Je vais soumettre une modification pour résoudre ce problème, mais je voulais juste laisser un commentaire FYIJe ne pense pas que vous le puissiez, la seule autre alternative de configuration est d'énumérer les chemins que vous souhaitez filtrer, donc au lieu de
/*
vous pouvez en ajouter pour/this/*
et/that/*
etc., mais cela ne conduira pas à une solution suffisante lorsque vous en avez beaucoup de ces chemins.Ce que vous pouvez faire est d'ajouter un paramètre au filtre en fournissant une expression (comme une expression régulière) qui est utilisée pour ignorer la fonctionnalité de filtre pour les chemins correspondants. Le conteneur de servlet appellera toujours votre filtre pour ces URL, mais vous aurez un meilleur contrôle sur la configuration.
Éditer
Maintenant que vous mentionnez que vous n'avez aucun contrôle sur le filtre, vous pouvez soit hériter de l'appel de ce filtre
super
méthodes d' dans ses méthodes, sauf lorsque le chemin d'url que vous souhaitez ignorer est présent et de suivre la chaîne de filtres comme @BalusC proposé, soit de construire un filtre qui instancie votre filtre et délègue dans les mêmes circonstances. Dans les deux cas, les paramètres de filtre incluent à la fois le paramètre d'expression que vous ajoutez et ceux du filtre dont vous héritez ou auquel vous déléguez.L'avantage de créer un filtre délégant (un wrapper) est que vous pouvez ajouter la classe de filtre du filtre enveloppé en tant que paramètre et la réutiliser dans d'autres situations comme celle-ci.
la source
J'ai également dû filtrer en fonction du modèle d'URL (/ {servicename} / api / stats /) dans le code java.
Mais c'est bizarre, ce servlet ne prend pas en charge les modèles d'URL autres que (/ *), ce devrait être un cas très courant pour les API de servlet!
la source
J'ai rencontré le même problème, mais je trouve une réponse ci-dessous.
web.xml
filter.java
de cette façon, vous n'avez pas à harceler la classe Filter concrète.
la source
Si, pour une raison quelconque, vous ne pouvez pas modifier le mappage de filtre d'origine ("/ *" dans mon cas) et que vous envoyez vers un filtre tiers non modifiable, vous pouvez trouver utile ce qui suit:
Les travaux suivants dans Weblogic 12.1.3:
la source