Разделительный контекст Spring для делегированияFilterProxy

Я пытаюсь установить фильтр в веб-приложение Spring с помощью DelegatingFilterProxy. Приложение - черный ящик для меня. У меня нет контроля над этим, но я знаю, что использует Spring. Я управляю только моим фильтром.

Само приложение настроено в web.xml(tomcat 7) обычным способом с помощью <listener>...ContextLoaderListener...</listener> с конфигурацией Spring, указанной через .

Моя первая попытка состояла в том, чтобы разделить контекст приложения. Я добавил собственный XML-конфигурацию Spring в context-param. Мой фильтр загружается просто отлично, но я сломал приложение. Я не уверен, как он сломался, но похоже, что он больше не может подключаться к базе данных. Я проверил очевидные вещи. Конфликтов имен компонентов и конфликтов имен нет.

Мне бы хотелось, чтобы у меня было 2 совершенно разных контекста, так что, по-видимому, не было бы никакого способа повлиять на фильтр для приложения черного ящика. Есть ли способ, которым я могу настроить web.xml, чтобы заставить Spring создавать новый контекст только для моего фильтра?

Есть несколько аналогичных вопросов по stackoverflow, но детали значительно отличаются.

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

Мои части ниже - это объявление фильтра и сопоставление фильтра, а вторая строка конфигурации контекста весны xml (classpath:...)

<!--?xml version="1.0" encoding="UTF-8"?-->

<web-app>

 <display-name>xxx</display-name>
 <description>xxx</description>

 <filter>
 <filter-name>myAccessFilter</filter-name>
 <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
 </filter>

 <filter-mapping>
 <filter-name>myAccessFilter</filter-name>
 <url-pattern>/*</url-pattern>
 </filter-mapping>

 <context-param>
 <param-name>log4jConfigLocation</param-name>
 <param-value>/WEB-INF/log4j.properties</param-value>
 </context-param>

 <context-param>
 <param-name>contextConfigLocation</param-name>
 <param-value>
 /WEB-INF/spring/applicationContext.xml
 classpath:my-access-spring.xml
 </param-value>
 </context-param>

 <listener>
 <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
 </listener>

 <listener>
 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>

 <listener>
 <listener-class>flex.messaging.HttpFlexSession</listener-class>
 </listener>

 <servlet>
 <servlet-name>spring-flex</servlet-name>
 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
 <init-param>
 <param-name>contextConfigLocation</param-name>
 
 </init-param>
 <load-on-startup>1</load-on-startup>
 </servlet>

 <servlet>
 <servlet-name>xxx-rest</servlet-name>
 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
 <load-on-startup>1</load-on-startup>
 </servlet>

 <!-- Map all /messagbroker requests to the DispatcherServlet for handling -->
 <servlet-mapping>
 <servlet-name>spring-flex</servlet-name>
 <url-pattern>/messagebroker/*</url-pattern>
 </servlet-mapping>

 <servlet-mapping>
 <servlet-name>xxx-rest</servlet-name>
 <url-pattern>/rest/*</url-pattern>
 </servlet-mapping>

 <error-page>
 <error-code>401</error-code>
 <location>/error-401.html</location>
 </error-page>

 <welcome-file-list>
 <welcome-file>index.html</welcome-file>
 <welcome-file>index.htm</welcome-file>
 <welcome-file>index.jsp</welcome-file>
 </welcome-file-list>

</web-app>

Прошло время: у меня есть дополнительная информация о том, почему общий контекст в этой ситуации - плохая идея. Оказывается, у меня были конфликты фанов. В частности, как мой фильтр, так и основное приложение использовали компонент "dataSource" (конечно).

Как только я переименовал свой bean-компонент, я получил очень четкое сообщение от Spring:

Определяющий компонент типа [javax.sql.DataSource] не определен: ожидаемый единичный компонент соответствия, но найден 2: dataSource, deoDataSource

Предположительно, приложение использует проводку по типу, а не по имени, поэтому у меня есть очевидный конфликт.

Так! Оригинальный вопрос по-прежнему стоит: возможно ли настроить Spring для создания отдельного контекста только для моего фильтра?

Спасибо, Фред

1 ответ

Существует два способа решения вашей проблемы:

  • сделать весну не использовать ваши бобы для автопостановки
  • указать другой контекст весны для прокси-сервера фильтра

Отключить автопогрузку

Специфические бобы могут быть исключены в качестве автолюбителей с помощью XML config:

Определить второй контекст приложения

Я не был прав в своих комментариях к вашему вопросу - вы не можете заставить ContextLoaderListener загружать два отдельных контекста. Но вы можете взломать, используя DispatcherServlet для загрузки второго контекста для вас:

<!-- Use this just to load second application context -->
<servlet>
 <servlet-name>filterContextLoader</servlet-name>
 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
 <init-param>
 <param-name>contextConfigLocation</param-name>
 <param-value>classpath:filter-context.xml</param-value>
 </init-param>
 <init-param>
 <param-name>contextAttribute</param-name>
 <param-value>filterContext</param-value>
 </init-param>
</servlet>

<filter>
 <filter-name>customFilter</filter-name>
 <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
 <init-param>
 <param-name>contextAttribute</param-name>
 <param-value>filterContext</param-value>
 </init-param>
</filter>

Конечно, есть недостаток, который DispatcherServlet будет использовать так называемые стратегии по умолчанию и автоматически регистрирует всевозможные ненужные компоненты (сопоставления обработчиков по умолчанию, адаптеры обработчиков,...). Но это должно быть безобидным. Если вы хотите зарегистрировать чистый контекст без ненужных компонентов, вам нужно будет реализовать свой собственный ServletContextListener для этого.

licensed under cc by-sa 3.0 with attribution.