Можем ли мы использовать регулярные выражения в шаблонах 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 выше шаблон фильтра должен совпадать. Как мне этого добиться?
6 ответов
Нет, вы не можете использовать регулярные выражения там. Согласно Спецификации Java-сервлета v2.4 (раздел srv.11.1), URL-путь интерпретируется следующим образом:
- Строка, начинающаяся с символа '/' и заканчивающаяся суффиксом '/*', используется для отображения пути.
- Строка, начинающаяся с '*.' Префикс используется как отображение расширения.
- Строка, содержащая только символ "/", обозначает сервлет "по умолчанию" приложения. В этом случае путь сервлета является URI запроса минус контекстный путь, а информация о пути равна нулю.
- Все остальные строки используются только для точных совпадений.
Не допускаются регулярные выражения. Даже не сложные подстановочные знаки.
Как отмечали другие, нет способа фильтрации с сопоставлением по регулярному выражению, используя только основные функции фильтра сервлета. Спецификация сервлета, скорее всего, написана так, чтобы обеспечить эффективное сопоставление 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 для исключения шаблонов, который оставляется в качестве упражнения для читателя.)
Ваш URL не будет работать, так как он не является допустимым шаблоном URL. Вы можете сослаться на следующий ответ
Это не сработает, здесь нельзя использовать регулярные выражения. Попробуйте использовать эти 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>
В web.xml
для сопоставления сервлетов можно использовать подстановочный знак только на start
или end
, если вы попытаетесь применить подстановочный знак между отображением не будет выбран.
Предыдущие ответы верны в том, что шаблон 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);
}
}