Как заставить OpenSessionInViewFilter исключать статические ресурсы
Я реализовал OpenSessionInViewFilter для моего веб-приложения MVC, и он работает почти идеально. Единственная проблема заключается в том, что он также создает сеанс для каждого изображения, js, css и т. Д., Запрашиваемых с веб-сервера. Это я не хочу.
Я использую Struts2, Spring и Hibernate, и это мой web.xml
<filter>
<filter-name>lazyLoadingFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>lazyLoadingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Так как я сопоставляю шаблон url /*, он также принимает все изображения и т. Д. Я попытался установить для него значения *.jsp и *.action, но затем я снова получаю исключения lazyloading... Как мне это сделать?? Я искал ответы в течение 5 часов, и я немного схожу с ума в моей голове.
Все, что мне нужно сделать, это сделать этот фильтр игнорировать все статические ресурсы. Это оно! И для всего остального он может работать. Это звучит так просто, но это действительно очень раздражает меня, что я не могу понять, как.
Любая помощь будет очень ценна.
Нужно ли расширять фильтр, чтобы написать собственный фильтр и исключить его? И если это так. Как?
РЕДАКТИРОВАТЬ: Кажется, что я мог бы настроить сопоставления фильтров для моих статических файлов в верхней части цепочки фильтров. А затем отправьте их в "ByPassFilter", минуя цепочку фильтров для этих статических ресурсов. Это путь?
Спасибо, парни!
5 ответов
Что касается вашей реализации наличия Bypassfilter, если у вас есть такой фильтр впереди, то, как только вы пропустите следующий фильтр в цепочке фильтров, тогда в основном остальные фильтры в цепочке также будут пропущены (что, кажется, не быть желательной вещью в большинстве ситуаций) . Также, как вызовы фильтра для запроса ведут себя как
Filter1 -> Filter2 ->Struts Action/BL -> Filter 2 -> Filter 1
Следовательно, OpenSessionInViewFilter сработает после обработки запроса в вашем действии Struts (этого можно избежать, установив другой обходной фильтр после открытого сеанса в фильтре представления в web.xml) . Однако в целом мне всегда казалось нежелательным пропускать всю цепочку фильтров для пропуска одного фильтра.
Я никогда не сталкивался с необходимостью пропустить OpenSessionInViewFilter, однако, если бы мне пришлось это сделать, то вместо Bypassfilter у меня был бы фильтр, расширяющий фильтр OpenSessionInViewFilter, который пропускал бы мои статические ресурсы из обработки.
Общая практика в таком сценарии заключается в использовании комбинации веб-сервера Apache с сервером приложений (Tomcat/JBoss) с модулем mod_jk.
Вот ссылка, описывающая, как использовать эту комбинацию. ( Еще одна ссылка)
Главное преимущество использования этой конфигурации
- Статический контент может обслуживаться веб-сервером Apache.
- Запросы динамического содержимого (например, *.jsp, *.action и т. Д.) Делегируются tomcat.
- Могут быть и другие полезные модули, такие как сжатие контентов для статического содержимого, что улучшает время отклика.
- Это более безопасно, чем сценарий, в котором сервер приложений обслуживает все.
Я понимаю, что это может быть не совсем то решение, которое вы ищете, я предложил это, так как это общая практика.
Включайте только те элементы шаблона, которые вам нужны.
Что-то вроде этого:
<filter-mapping>
<filter-name>lazyLoadingFilter</filter-name>
<url-pattern>*.html</url-pattern>
<url-pattern>/profile/edit</url-pattern>
<url-pattern>/cars/*</url-pattern>
</filter-mapping>
На всякий случай кому-то нужно решение с расширением OpenSessionInViewFilter
, Это предотвращает создание сеанса Hibernate для предварительно определенных статических ресурсов.
/**
* Skips OpenSessionInViewFilter logic for static resources
*/
public class NonStaticOpenSessionInViewFilter extends OpenSessionInViewFilter {
static final Pattern STATIC_RESOURCES = Pattern.compile("(^/js/.*)|(^/css/.*)|(^/img/.*)|(^/fonts/.*)|(/favicon.ico)");
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String path = request.getServletPath();
if (STATIC_RESOURCES.matcher(path).matches()) {
filterChain.doFilter(request, response);
} else {
super.doFilterInternal(request, response, filterChain);
}
}
}
В основном Spring должен был предоставить некоторые свойства, такие как excludePatterns
за OpenSessionInViewFilter
,
Я полностью согласен с ответом @Santosh.
OpenSessionInViewFilter
создает ресурс и добавляет его ThreadLocal
Если сеанс никогда не используется, то сеанс фактически никогда не создается, это также означает, что соединение db не используется для этого запроса. (это, вероятно, ответ на ваш вопрос).
Если вам все еще требуется контролировать вещи, вы всегда можете создать еще один фильтр, расширяющий OpenSessionInViewFilter
и выполнить getSession
метод, основанный на том, какой ресурс вызывается.