Подтвердить что ты не робот

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

Ответ 3

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

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

Ответ 4

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

Ответ 5

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

Ответ 6

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

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

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

Конфигурация фильтра в файле 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 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);
    }
}