web-dev-qa-db-fra.com

Pouvons-nous utiliser des expressions régulières dans les modèles d'URL web.xml?

J'écris un filtre pour effectuer une tâche spécifique mais je ne parviens pas à définir un modèle d'URL spécifique pour mon filtre. Ma cartographie de filtre est la suivante:

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

Mon URL-pattern [ /org/test/ * /keys/ * ] ne fonctionne pas comme prévu.

J'appelle les URL du navigateur comme: 

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

Donc, pour les URL ci-dessus, le modèle de filtre doit correspondre. Comment puis-je atteindre cet objectif?

31
Satya

Non, vous ne pouvez pas utiliser de regex ici. Selon la spécification Java Servlet v2.4 (section srv.11.1), le chemin d’URL est interprété comme suit:

  • Une chaîne commençant par un caractère "/" et se terminant par un suffixe "/ *" est utilisée pour le mappage de chemin.
  • Une chaîne commençant par un préfixe «*.» Est utilisée comme mappage d’extension.
  • Une chaîne ne contenant que le caractère ’/’ indique le servlet "par défaut" de l’application. Dans ce cas, le chemin de la servlet est le L'URI de la requête moins le chemin du texte et les informations sur le chemin sont nulles.
  • Toutes les autres chaînes sont utilisées uniquement pour les correspondances exactes.

Aucune expression rationnelle n'est autorisée. Pas même les wild-cards compliquées.

40
Stephen C

Comme l'ont noté d'autres personnes, il n'existe aucun moyen de filtrer avec une correspondance d'expression régulière en utilisant uniquement les fonctionnalités de filtre de servlet de base. La spécification de servlet est probablement écrite comme elle permet une correspondance efficace des URL, et parce que les servlets sont antérieures à la disponibilité des expressions régulières en Java (les expressions régulières sont arrivées dans Java 1.4). 

Les expressions régulières seraient probablement moins performantes (non, je ne l'ai pas évalué), mais si vous n'êtes pas trop contraint par le temps de traitement et que vous souhaitez échanger les performances pour une facilité de configuration, procédez comme suit:

Dans votre filtre:

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.

    }
  }

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

Il est également parfois pratique de faire en sorte que le modèle exclue la correspondance en inversant l'instruction if dans doFilter() (ou ajoutez un autre paramètre init pour les motifs excluant, qui reste un exercice pour le lecteur.)

10
Gus

Votre URL ne fonctionnera pas car ce n'est pas un modèle d'URL valide. Vous pouvez vous référer à la réponse suivante

Spécification d'URL

6
havexz

Cela ne fonctionnera pas, aucune expression rationnelle ne peut être utilisée ici. Essayez d'utiliser ces URL pour votre application:

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

Et cette configuration pour votre web.xml:

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

dans web.xml pour le mappage de servlet, vous pouvez appliquer le caractère générique uniquement à la start ou à la end, si vous essayez d'appliquer le caractère générique entre les correspondances ne sera pas choisi.

0
dku.rajkumar

Les réponses précédentes sont correctes en ce sens qu'un motif d'URL ne peut commencer ou se terminer que par un caractère générique, de sorte que le véritable pouvoir de regex ne peut pas être utilisé.

Cependant, j'ai résolu ce problème sur des projets précédents en créant un filtre par défaut simple qui intercepte toutes les demandes et le filtre contient une expression régulière afin de déterminer si une logique supplémentaire doit être appliquée. J'ai trouvé qu'il y avait peu ou pas de dégradation des performances avec cette approche. 

Vous trouverez ci-dessous un exemple simple qui pourrait être amélioré en déplaçant le motif regex vers un attribut de filtre.

Filtrer la configuration dans le fichier 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>

Implémentation de filtre de base pouvant utiliser n'importe quel modèle regex (désolé, utilise la classe parent OncePerRequestFilter de Spring):

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