java - ¿Podemos usar expresiones regulares en patrones de URL web.xml?
servlet-filters (6)
Estoy escribiendo un filtro para hacer una tarea específica, pero no puedo establecer un patrón de URL específico para mi filtro. Mi asignación de filtros es la siguiente:
<web.xml>
<filter>
<filter-name>myFilter</filter-name>
<filter-class>test.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>myFilter</filter-name>
<url-pattern>/org/test/*/keys/*</url-pattern>
</filter-mapping>
</web-app>
Mi url-pattern [ /org/test/ * /keys/ * ]
no funciona como esperaba.
Estoy llamando urls desde el navegador como:
http://localhost:8080/myapp/org/test/SuperAdminReport/keys/superAdminReport.jsp
http://localhost:8080/myapp/org/test/Adminreport/keys/adminReport.jsp
http://localhost:8080/myapp/org/test/OtherReport/keys/otherReport.jsp
Por lo tanto, para las URL anteriores, el patrón de filtro debe coincidir. ¿Cómo puedo conseguir esto?
Como señalaron otros, no hay forma de filtrar con la coincidencia de expresiones regulares utilizando solo las características básicas del filtro de servlets. Es probable que la especificación del servlet esté escrita de la forma en que permite una correspondencia eficiente de las URL, y porque los servlets son anteriores a la disponibilidad de las expresiones regulares en Java (las expresiones regulares llegaron a Java 1.4).
Las expresiones regulares probablemente sean menos efectivas (no, no lo he comparado), pero si no estás muy limitado por el tiempo de procesamiento y deseas cambiar el rendimiento para facilitar la configuración, puedes hacerlo así:
En tu filtro:
private String subPathFilter = ".*";
private Pattern pattern;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String subPathFilter = filterConfig.getInitParameter("subPathFilter");
if (subPathFilter != null) {
this.subPathFilter = subPathFilter;
}
pattern = Pattern.compile(this.subPathFilter);
}
public static String getFullURL(HttpServletRequest request) {
// Implement this if you want to match query parameters, otherwise
// servletRequest.getRequestURI() or servletRequest.getRequestURL
// should be good enough. Also you may want to handle URL decoding here.
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
Matcher m = pattern.matcher(getFullURL((HttpServletRequest) servletRequest));
if (m.matches()) {
// filter stuff here.
}
}
Luego en web.xml ...
<filter>
<filter-name>MyFiltersName</filter-name>
<filter-class>com.konadsc.servlet.MyFilter</filter-class>
<init-param>
<param-name>subPathFilter</param-name>
<param-value>/org/test/[^/]+/keys/.*</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>MyFiltersName</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
También es a veces conveniente hacer que el patrón excluya la coincidencia invirtiendo la instrucción if en doFilter()
(o agregue otro param inicial para excluir patrones, que se deja como un ejercicio para el lector).
Eso no funcionará, no se puede usar regex allí. Intente usar estas URL para su aplicación:
http://localhost:8080/myapp/org/test/keys/SuperAdminReport/superAdminReport.jsp
http://localhost:8080/myapp/org/test/keys/Adminreport/adminReport.jsp
http://localhost:8080/myapp/org/test/keys/OtherReport/otherReport.jsp
Y esta configuración para su web.xml:
<filter-mapping>
<filter-name>myFilter</filter-name>
<url-pattern>/org/test/keys/*</url-pattern>
</filter-mapping>
Las respuestas anteriores son correctas, ya que un patrón de url solo puede comenzar o finalizar con un carácter de comodín y, por lo tanto, no se puede usar el verdadero poder de la expresión regular.
Sin embargo, he resuelto este problema en proyectos anteriores al crear un filtro predeterminado simple que intercepta todas las solicitudes y el filtro contiene expresiones regulares para determinar si se debe aplicar una lógica adicional. Descubrí que hubo poca o ninguna degradación del rendimiento con este enfoque.
A continuación se muestra un ejemplo simple que podría mejorarse moviendo el patrón de expresiones regulares a un atributo de filtro.
Configuración del filtro dentro de web.xml:
<filter>
<filter-name>SampleFilter</filter-name>
<filter-class>org.test.SampleFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SampleFilter</filter-name>
<servlet-name>SampleServlet</servlet-name>
</filter-mapping>
<servlet-mapping>
<servlet-name>SampleServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Implementación de filtro básico que podría usar cualquier patrón de expresiones regulares (lo sentimos, utiliza la clase primaria de Once de SpringPilverSolic).
public class SampleFilter extends OncePerRequestFilter {
@Override
final protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
if (applyLogic(request)) {
//Execute desired logic;
}
filterChain.doFilter(request, response);
}
protected boolean applyLogic(HttpServletRequest request) {
String path = StringUtils.removeStart(request.getRequestURI(), request.getContextPath());
return PatternMatchUtils.simpleMatch(new String[] { "/login" }, path);
}
}
No, no puedes usar una expresión regular allí. De acuerdo con Java Servlet Specification v2.4 (sección srv.11.1), url-path se interpreta de la siguiente manera:
- Una cadena que comienza con un carácter ''/'' y termina con un sufijo ''/ *'' se usa para el mapeo de ruta.
- Una cadena que comienza con un ''*'' el prefijo se usa como un mapeo de extensión.
- Una cadena que contiene solo el carácter ''/'' indica el servlet "predeterminado" de la aplicación. En este caso, la ruta del servlet es el URI de solicitud menos la ruta de entrada y la información de ruta es nula.
- Todas las demás cadenas se usan solo para coincidencias exactas.
No se permiten regexes. Ni siquiera complicadas cartas salvajes.
Su URL no funcionará ya que no es un patrón de URL válido. Puedes consultar la siguiente respuesta
Especificación de URL
en web.xml
para la asignación de servlets, puede aplicar comodines solo al start
o al end
, si intenta aplicar el comodín entre las asignaciones no se seleccionará.