Могу ли я исключить некоторые конкретные URL-адреса из <url-pattern> внутри <filter-mapping>?
127
Я хочу, чтобы какой-то конкретный фильтр применялся ко всем URL-адресам, кроме одного конкретного (то есть, /*кроме /specialpath).
Есть ли возможность это сделать?
образец кода:
<filter><filter-name>SomeFilter</filter-name><filter-class>org.somproject.AFilter</filter-class></filter><filter-mapping><filter-name>SomeFilter</filter-name><url-pattern>/*</url-pattern><!-- the question is: how to modify this line? --><dispatcher>REQUEST</dispatcher><dispatcher>FORWARD</dispatcher></filter-mapping>
Стандартный API сервлетов не поддерживает эту возможность. Вы можете использовать для этого фильтр rewrite-URL, подобный фильтру Tuckey (который очень похож на Apache HTTPD mod_rewrite), или добавить проверку doFilter()метода прослушивания Filter /*.
String path =((HttpServletRequest) request).getRequestURI();if(path.startsWith("/specialpath/")){
chain.doFilter(request, response);// Just continue chain.}else{// Do your business stuff here for all paths other than /specialpath.}
При необходимости вы можете указать пути, которые следует игнорировать, в качестве init-paramфильтра, чтобы вы могли контролировать его в web.xmlлюбом случае. Получить его в фильтре можно следующим образом:
Если фильтр является частью стороннего API и, таким образом, вы не можете его изменить, затем сопоставьте его с более конкретным url-pattern, например, /otherfilterpath/*и создайте новый фильтр, /*который будет перенаправлять на путь, соответствующий стороннему фильтру.
Чтобы избежать того, что этот фильтр будет вызывать себя в бесконечном цикле, вам нужно позволить ему только прослушивать (отправлять) REQUESTи только сторонний фильтр FORWARD.
Моя проблема в том, что фильтр не мой, это из библиотеки компонентов.
Roman
4
Ypu следует взять фильтр библиотеки компонентов и расширить его, чтобы добавить код, который вы хотите использовать для выполнения исключений.
gbtimmon
@BalusC Если "/ specialpath" просто обслуживает статический ресурс, такой как js, css и т. Д., Делает ли chain.doFilter () ответ медленнее? Есть ли способ обслуживать ресурс напрямую, не связывая фильтр?
BenhurCD
@BenhurCD: Я действительно понятия не имею, как вы вообще могли решить эту проблему с производительностью.
BalusC
13
Я использовал подход, описанный Эриком Догерти : я создал специальный сервлет, который всегда отвечает кодом 403 и помещал его отображение перед общим.
Этот подход работает, когда вы хотите запретить определенный фильтр и все последующие. Он должен хорошо работать, если вы, например. хотите использовать некоторый контент в качестве статических ресурсов в контейнере сервлетов вместо того, чтобы позволять логике вашего приложения (через фильтр вроде GuiceFilter):
Сопоставьте папку с вашими статическими файлами ресурсов сервлету по умолчанию. Создайте фильтр сервлета и поместите его перед GuiceFilter в вашем web.xml. В созданном вами фильтре вы можете разделить пересылку одних запросов в GuiceFilter и других напрямую диспетчеру. Пример следует ...
Я попытался использовать ваше решение, но для файлов, к которым я применяю фильтр и разрываю цепочку, я получаю следующую ошибку; Неперехваченное исключение, выброшенное фильтром. Фильтр статических ресурсов: java.io.FileNotFoundException. Есть идеи, почему?
шамалейте
В настройках с несколькими контекстами использование .getRequestURI()будет прервано (скорее всего, вызовет ошибку 404), потому что .getRequestDispatcherразрешается относительно пути контекста . Если ваш контекстный путь равен /a, то в вашем примере URI запроса будет /a/static, и использование getRequestDispatcher("/a/static")приведет к его разрешению /a/a/staticвместо этого. Исправление: используйте .getServletPath()вместо .getRequestURI(). Я отправлю правку, чтобы исправить это, но просто хотел оставить комментарий К вашему сведению
Рид
3
Я не думаю, что вы можете, единственная другая альтернатива конфигурации - это перечислить пути, которые вы хотите отфильтровать, поэтому вместо того, чтобы /*вы могли добавить некоторые для /this/*и /that/*т.д., но это не приведет к достаточному решению, когда у вас много этих путей.
Что вы можете сделать, так это добавить параметр к фильтру, предоставляющий выражение (например, регулярное выражение), которое используется для пропуска функции фильтра для сопоставленных путей. Контейнер сервлета по-прежнему будет вызывать ваш фильтр для этих URL-адресов, но у вас будет лучший контроль над конфигурацией.
редактировать
Теперь, когда вы упомянули, что у вас нет контроля над фильтром, вы можете либо унаследовать от этого superметода вызова фильтра в его методах, кроме случаев, когда путь URL-адреса, который вы хотите пропустить, присутствует, и следовать цепочке фильтров, например, предложенный @BalusC, либо построить фильтр, который создает ваш фильтр и делегирует его при тех же обстоятельствах. В обоих случаях параметры фильтра будут включать как параметр выражения, который вы добавляете, так и параметры фильтра, от которого вы наследуете или которому делегируете.
Преимущество создания делегирующего фильтра (оболочки) состоит в том, что вы можете добавить класс фильтра обернутого фильтра в качестве параметра и повторно использовать его в других ситуациях, подобных этой.
Если по какой-либо причине вы не можете изменить исходное сопоставление фильтров («/ *» в моем случае) и отправляете в неизменяемый сторонний фильтр, вы можете найти полезным следующее:
Перехватить путь, который нужно обойти
Перейти и выполнить последнее кольцо цепочки фильтров (сам сервлет)
Пропуск выполняется через отражение, проверяя экземпляры контейнера в режиме отладки.
Я использовал подход, описанный Эриком Догерти : я создал специальный сервлет, который всегда отвечает кодом 403 и помещал его отображение перед общим.
Фрагмент карты:
И класс сервлета:
источник
Этот подход работает, когда вы хотите запретить определенный фильтр и все последующие. Он должен хорошо работать, если вы, например. хотите использовать некоторый контент в качестве статических ресурсов в контейнере сервлетов вместо того, чтобы позволять логике вашего приложения (через фильтр вроде GuiceFilter):
Сопоставьте папку с вашими статическими файлами ресурсов сервлету по умолчанию. Создайте фильтр сервлета и поместите его перед GuiceFilter в вашем web.xml. В созданном вами фильтре вы можете разделить пересылку одних запросов в GuiceFilter и других напрямую диспетчеру. Пример следует ...
web.xml
StaticResourceFilter.class
К сожалению, если вы просто хотите пропустить один шаг в цепочке фильтров, сохранив следующие, это не сработает.
источник
.getRequestURI()
будет прервано (скорее всего, вызовет ошибку 404), потому что.getRequestDispatcher
разрешается относительно пути контекста . Если ваш контекстный путь равен/a
, то в вашем примере URI запроса будет/a/static
, и использованиеgetRequestDispatcher("/a/static")
приведет к его разрешению/a/a/static
вместо этого. Исправление: используйте.getServletPath()
вместо.getRequestURI()
. Я отправлю правку, чтобы исправить это, но просто хотел оставить комментарий К вашему сведениюЯ не думаю, что вы можете, единственная другая альтернатива конфигурации - это перечислить пути, которые вы хотите отфильтровать, поэтому вместо того, чтобы
/*
вы могли добавить некоторые для/this/*
и/that/*
т.д., но это не приведет к достаточному решению, когда у вас много этих путей.Что вы можете сделать, так это добавить параметр к фильтру, предоставляющий выражение (например, регулярное выражение), которое используется для пропуска функции фильтра для сопоставленных путей. Контейнер сервлета по-прежнему будет вызывать ваш фильтр для этих URL-адресов, но у вас будет лучший контроль над конфигурацией.
редактировать
Теперь, когда вы упомянули, что у вас нет контроля над фильтром, вы можете либо унаследовать от этого
super
метода вызова фильтра в его методах, кроме случаев, когда путь URL-адреса, который вы хотите пропустить, присутствует, и следовать цепочке фильтров, например, предложенный @BalusC, либо построить фильтр, который создает ваш фильтр и делегирует его при тех же обстоятельствах. В обоих случаях параметры фильтра будут включать как параметр выражения, который вы добавляете, так и параметры фильтра, от которого вы наследуете или которому делегируете.Преимущество создания делегирующего фильтра (оболочки) состоит в том, что вы можете добавить класс фильтра обернутого фильтра в качестве параметра и повторно использовать его в других ситуациях, подобных этой.
источник
Мне также пришлось фильтровать на основе шаблона URL (/ {servicename} / api / stats /) в java-коде.
Но странно, что сервлет не поддерживает шаблон URL, отличный от (/ *). Это должно быть очень распространенным случаем для API сервлетов!
источник
Я столкнулся с той же проблемой, но я нашел ответ, показанный ниже.
web.xml
filter.java
таким образом вам не нужно беспокоить конкретный класс Filter.
источник
Если по какой-либо причине вы не можете изменить исходное сопоставление фильтров («/ *» в моем случае) и отправляете в неизменяемый сторонний фильтр, вы можете найти полезным следующее:
В Weblogic 12.1.3 работает следующее:
источник