¿Puedo excluir algunas URL concretas de <url-pattern> dentro de <filter-mapping>?
127
Quiero que se aplique un filtro de concreto para todas las URL excepto para un concreto (es decir, /*excepto para /specialpath).
¿Existe la posibilidad de hacer eso?
Código de muestra:
<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>
La API de Servlet estándar no es compatible con esta instalación. Es posible que desee utilizar un filtro de reescritura de URL para esto, como el de Tuckey (que es muy similar al de Apache HTTPD mod_rewrite), o agregar una verificación en el doFilter()método de escucha del filtro /*.
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.}
Si es necesario, puede especificar las rutas a ignorar como parte init-paramdel filtro para poder controlarlo de web.xmltodos modos. Puede obtenerlo en el filtro de la siguiente manera:
Si el filtro es parte de la API de un tercero y, por lo tanto, no puede modificarlo, entonces asigne un mapa más específico url-pattern, por ejemplo, /otherfilterpath/*y cree un nuevo filtro /*que reenvíe a la ruta que coincida con el filtro de un tercero.
Para evitar que este filtro se llame a sí mismo en un bucle infinito, debe dejarlo escuchar (despachar) REQUESTsolo y el filtro de terceros FORWARDsolo.
Mi problema es que el filtro no es mío, es de la biblioteca de componentes.
Romano
44
Ypu debe tomar el filtro de la biblioteca de componentes y extenderlo para agregar el código que desea usar para realizar las exclusiones.
gbtimmon
@BalusC Si el "/ specialpath" solo sirve un recurso estático como js, css, etc., ¿chain.doFilter () hace que la respuesta sea más lenta? ¿Hay algún método para servir el recurso directamente sin encadenar el filtro?
BenhurCD
@BenhurCD: Realmente no tengo idea de cómo podrías llegar a este problema de rendimiento.
BalusC
13
Utilicé un enfoque descrito por Eric Daugherty : creé un servlet especial que siempre responde con el código 403 y puse su mapeo antes que el general.
Este enfoque funciona cuando desea evitar cierto filtro y todos los siguientes. Debería funcionar bien si, por ejemplo. desea servir algún contenido como recursos estáticos dentro de su contenedor de servlet en lugar de permitir la lógica de su aplicación (a través de un filtro como GuiceFilter):
Asigne la carpeta con sus archivos de recursos estáticos al servlet predeterminado. Cree un filtro de servlet y póngalo antes del GuiceFilter en su web.xml. En su filtro creado, puede separarse entre reenviar algunas solicitudes al GuiceFilter y otras directamente al despachador. El siguiente ejemplo ...
Intenté ir con su solución, pero para los archivos que aplico el filtro y rompo la cadena, aparece el siguiente error; Excepción no detectada generada por el filtro Filtro de recursos estáticos: java.io.FileNotFoundException. ¿Alguna idea de por qué?
shamaleyte
En configuraciones de contexto múltiple, el uso .getRequestURI()se interrumpirá (lo que probablemente causará un 404) porque se .getRequestDispatcherresuelve en relación con la ruta de contexto . Si su ruta de contexto es /a, entonces, en su ejemplo, el URI de la solicitud sería /a/static, y el uso getRequestDispatcher("/a/static")hará que se resuelva en su /a/a/staticlugar. Solución: use en .getServletPath()lugar de .getRequestURI(). Enviaré una edición para arreglar esto, pero solo quería dejar un comentario FYI
Reid
3
No creo que pueda, la única otra alternativa de configuración es enumerar las rutas que desea filtrar, por lo que en lugar de /*poder agregar algunas para /this/*y /that/*etc., pero eso no conducirá a una solución suficiente cuando tenga mucho de esos caminos
Lo que puede hacer es agregar un parámetro al filtro que proporcione una expresión (como una expresión regular) que se utiliza para omitir la funcionalidad del filtro para las rutas coincidentes. El contenedor de servlet aún llamará a su filtro para esas URL, pero tendrá un mejor control sobre la configuración.
Editar
Ahora que mencionas que no tienes control sobre el filtro, lo que puedes hacer es heredar de ese supermétodo los métodos de llamada en sus métodos, excepto cuando la ruta de URL que quieres omitir está presente y seguir la cadena de filtros como @BalusC propuso, o construir un filtro que crea instancias de su filtro y delega en las mismas circunstancias. En ambos casos, los parámetros del filtro incluirían tanto el parámetro de expresión que agregue como los del filtro del que herede o delegue.
La ventaja de crear un filtro de delegación (un contenedor) es que puede agregar la clase de filtro del filtro ajustado como parámetro y reutilizarlo en otras situaciones como esta.
Si por alguna razón no puede cambiar la asignación del filtro original ("/ *" en mi caso) y está enviando a un filtro de terceros inmutable, puede encontrar útil lo siguiente:
Interceptar el camino a ser ignorado
Salte y ejecute el último anillo de la cadena de filtro (el servlet mismo)
El salto se realiza mediante reflexión, inspeccionando las instancias del contenedor en modo de depuración
Utilicé un enfoque descrito por Eric Daugherty : creé un servlet especial que siempre responde con el código 403 y puse su mapeo antes que el general.
Fragmento de mapeo:
Y la clase de servlet:
fuente
Este enfoque funciona cuando desea evitar cierto filtro y todos los siguientes. Debería funcionar bien si, por ejemplo. desea servir algún contenido como recursos estáticos dentro de su contenedor de servlet en lugar de permitir la lógica de su aplicación (a través de un filtro como GuiceFilter):
Asigne la carpeta con sus archivos de recursos estáticos al servlet predeterminado. Cree un filtro de servlet y póngalo antes del GuiceFilter en su web.xml. En su filtro creado, puede separarse entre reenviar algunas solicitudes al GuiceFilter y otras directamente al despachador. El siguiente ejemplo ...
web.xml
StaticResourceFilter.class
Desafortunadamente, si solo desea omitir un solo paso en la cadena de filtros mientras mantiene los siguientes, esto no funcionará.
fuente
.getRequestURI()
se interrumpirá (lo que probablemente causará un 404) porque se.getRequestDispatcher
resuelve en relación con la ruta de contexto . Si su ruta de contexto es/a
, entonces, en su ejemplo, el URI de la solicitud sería/a/static
, y el usogetRequestDispatcher("/a/static")
hará que se resuelva en su/a/a/static
lugar. Solución: use en.getServletPath()
lugar de.getRequestURI()
. Enviaré una edición para arreglar esto, pero solo quería dejar un comentario FYINo creo que pueda, la única otra alternativa de configuración es enumerar las rutas que desea filtrar, por lo que en lugar de
/*
poder agregar algunas para/this/*
y/that/*
etc., pero eso no conducirá a una solución suficiente cuando tenga mucho de esos caminosLo que puede hacer es agregar un parámetro al filtro que proporcione una expresión (como una expresión regular) que se utiliza para omitir la funcionalidad del filtro para las rutas coincidentes. El contenedor de servlet aún llamará a su filtro para esas URL, pero tendrá un mejor control sobre la configuración.
Editar
Ahora que mencionas que no tienes control sobre el filtro, lo que puedes hacer es heredar de ese
super
método los métodos de llamada en sus métodos, excepto cuando la ruta de URL que quieres omitir está presente y seguir la cadena de filtros como @BalusC propuso, o construir un filtro que crea instancias de su filtro y delega en las mismas circunstancias. En ambos casos, los parámetros del filtro incluirían tanto el parámetro de expresión que agregue como los del filtro del que herede o delegue.La ventaja de crear un filtro de delegación (un contenedor) es que puede agregar la clase de filtro del filtro ajustado como parámetro y reutilizarlo en otras situaciones como esta.
fuente
También tuve que filtrar según el patrón de URL (/ {servicename} / api / stats /) en el código de Java.
Pero es extraño, ese servlet no admite un patrón de URL que no sea (/ *). ¡Este debería ser un caso muy común para las API de servlet!
fuente
Me he encontrado con el mismo problema, pero encuentro una respuesta que se muestra a continuación.
web.xml
filter.java
de esta manera no tiene que acosar a la clase de filtro concreto.
fuente
Si por alguna razón no puede cambiar la asignación del filtro original ("/ *" en mi caso) y está enviando a un filtro de terceros inmutable, puede encontrar útil lo siguiente:
Los siguientes trabajos en Weblogic 12.1.3:
fuente