it-swarm.com.ru

Можем ли мы использовать регулярные выражения в шаблонах URL web.xml?

Я пишу фильтр для выполнения определенной задачи, но я не могу установить определенный шаблон 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 выше шаблон фильтра должен совпадать. Как мне этого добиться?

31
Satya

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

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

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

40
Stephen C

Как отмечали другие, нет способа фильтрации с сопоставлением по регулярному выражению, используя только основные функции фильтра сервлета. Спецификация сервлета, скорее всего, написана так, чтобы обеспечить эффективное сопоставление 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 для исключения шаблонов, который оставляется в качестве упражнения для читателя).

10
Gus

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

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

6
havexz

Это не сработает, здесь нельзя использовать регулярные выражения. Попробуйте использовать эти 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>
3
I.G. Pascual

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

0
dku.rajkumar

Предыдущие ответы верны в том, что шаблон 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
Adam