Можем ли мы использовать регулярные выражения в шаблонах URL web.xml? - PullRequest
32 голосов
/ 20 декабря 2011

Я пишу фильтр для выполнения определенной задачи, но я не могу установить определенный шаблон URL для моего фильтра. Мое сопоставление фильтра выглядит следующим образом:

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

Мой шаблон URL [ /org/test/ * /keys/ * ] не работает, как я ожидал.

Я звоню по URL из браузера, как:

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

Так что для URL выше шаблон фильтра должен совпадать. Как мне этого добиться?

Ответы [ 6 ]

41 голосов
/ 20 декабря 2011

Нет, вы не можете использовать регулярные выражения там.Согласно Спецификации Java-сервлета v2.4 (раздел srv.11.1), URL-путь интерпретируется следующим образом:

  • Строка, начинающаяся с символа '/' и заканчивающаяся символомСуффикс '/ *' используется для отображения пути.
  • Строка, начинающаяся с '*.'префикс используется как отображение расширения.
  • Строка, содержащая только символ '/', указывает сервлет приложения по умолчанию.В этом случае путь сервлета - это URI запроса минус контекстный путь, а информация о пути - ноль.
  • Все остальные строки используются только для точных совпадений.

Не допускаются регулярные выражения.Даже не сложные подстановочные знаки.

11 голосов
/ 11 апреля 2014

Как отмечали другие, нет способа фильтрации с сопоставлением регулярных выражений, используя только базовые функции фильтра сервлетов.Спецификация сервлета, скорее всего, написана так, чтобы обеспечить эффективное сопоставление URL-адресов, а также потому, что сервлеты предшествуют доступности регулярных выражений в Java (регулярные выражения появились в Java 1.4).

Регулярные выражения, вероятно, будут менее производительными (нет, я их не тестировал), но если вы не сильно ограничены временем обработки и хотите торговать производительностью для простоты настройки, вы можете сделать это следующим образом:

В вашем фильтре:

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.

    }
  }

Затем в 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>

Это также иногдаудобно, чтобы шаблон исключал совпадение, инвертируя оператор if в doFilter() (или добавляя другой параметр init для исключений шаблонов, который оставляется в качестве упражнения для читателя.)

5 голосов
/ 20 декабря 2011

Ваш URL не будет работать, так как он не является допустимым шаблоном URL. Вы можете сослаться на следующий ответ

Спецификация URL

3 голосов
/ 20 декабря 2011

Это не сработает, здесь нельзя использовать регулярные выражения. Попробуйте использовать эти URL для вашего приложения:

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

И этот конфиг для вашего web.xml:

<filter-mapping>
    <filter-name>myFilter</filter-name>
    <url-pattern>/org/test/keys/*</url-pattern>
</filter-mapping>
0 голосов
/ 28 декабря 2012

Предыдущие ответы верны в том, что шаблон URL может начинаться или заканчиваться только символом подстановки, и, следовательно, истинная сила регулярного выражения не может быть использована.

Однако я решил эту проблему в предыдущих проектах, создав простой фильтр по умолчанию, который перехватывает все запросы, и этот фильтр содержит регулярные выражения для определения необходимости применения дальнейшей логики. Я обнаружил, что при таком подходе снижение производительности было незначительным.

Ниже приведен простой пример, который можно улучшить, переместив шаблон регулярного выражения в атрибут фильтра.

Настройка фильтра в файле 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>

Базовая реализация фильтра, которая может использовать любой шаблон регулярных выражений (извините, использует родительский класс Spring's 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 голосов
/ 20 декабря 2011

in web.xml для сопоставления сервлета. Вы можете использовать подстановочный знак только в start или end, если вы попытаетесь применить подстановочный знак в промежутке между сопоставлением, не будет выбран.

...