it-swarm-pt.tech

Podemos usar expressões regulares em padrões de URL web.xml?

Estou escrevendo um filtro para fazer uma tarefa específica, mas não consigo definir um padrão de URL específico para meu filtro. Meu mapeamento de filtro é o seguinte:

 <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>

Meu padrão de URL [ /org/test/ * /keys/ * ] não está funcionando como eu esperava.

Estou chamando URLs do 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

Portanto, para os URLs acima, o padrão de filtro deve corresponder. Como posso conseguir isso?

31
Satya

Não, você não pode usar um regex lá. De acordo com a Java Servlet Specification v2.4 (seção srv.11.1), o caminho-url é interpretado da seguinte forma:

  • Uma sequência que começa com um caractere "/" e termina com um sufixo "/ *" é usada para o mapeamento de caminho.
  • Uma sequência que começa com um prefixo "*" é usada como um mapeamento de extensão.
  • Uma string contendo apenas o caractere '/' indica o servlet "padrão" do aplicativo. Nesse caso, o caminho do servlet é o URI da solicitação Menos o caminho do contexto e a informação do caminho é nula.
  • Todas as outras strings são usadas apenas para correspondências exatas.

Nenhuma regex é permitida. Nem mesmo complicados cartões-selvagens.

40
Stephen C

Como observado por outros, não há como filtrar com correspondência de expressão regular usando apenas os recursos básicos do filtro de servlet. É provável que a especificação do servlet seja gravada da maneira que é para permitir a correspondência eficiente de urls e porque os servlets são anteriores à disponibilidade de expressões regulares em Java (expressões regulares chegaram no Java 1.4). 

Expressões regulares provavelmente seriam de menor desempenho (não, eu não o fiz comparativo), mas se você não está fortemente limitado pelo tempo de processamento e deseja trocar desempenho por facilidade de configuração, você pode fazer assim:

No seu 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.

    }
  }

Então, em 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>

Às vezes também é conveniente fazer com que o padrão exclua a correspondência invertendo a instrução if em doFilter() (ou adicione outro parametro init para excluir padrões, que é deixado como um exercício para o leitor).

10
Gus

Sua URL não funcionará, pois não é um padrão de URL válido. Você pode consultar a seguinte resposta

especificação de URL

6
havexz

Isso não funciona, nenhum regex pode ser usado lá. Tente usar esses URLs para seu aplicativo:

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

E esta configuração para o seu web.xml:

<filter-mapping>
    <filter-name>myFilter</filter-name>
    <url-pattern>/org/test/keys/*</url-pattern>
</filter-mapping>
3
I.G. Pascual

em web.xml para mapeamento de servlet, você pode aplicar curinga somente em start ou end, se você tentar aplicar o caractere curinga entre o mapeamento não será selecionado.

0
dku.rajkumar

As respostas anteriores estão corretas na medida em que um padrão de URL só pode começar ou terminar com um caractere curinga e, portanto, o verdadeiro poder da regex não pode ser usado.

No entanto, resolvi esse problema em projetos anteriores criando um filtro padrão simples que intercepta todas as solicitações e o filtro contém regex para determinar se outras lógicas devem ser aplicadas. Descobri que havia pouca ou nenhuma degradação no desempenho com essa abordagem. 

Abaixo está um exemplo simples que pode ser aprimorado ao mover o padrão de expressão regular para um atributo de filtro.

Configuração de filtro no 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>

Implementação de filtro básico que poderia usar qualquer padrão regex (desculpe, usa a classe pai do Spring OncePerRequestFilter):

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);
    }
}
0
Adam