ContextLoaderListener или нет?
Стандартное веб-приложение spring (созданное с помощью шаблона Roo или "Spring MVC Project" ) создает web.xml с ContextLoaderListener
и DispatcherServlet
. Почему они не только используют DispatcherServlet
и загружают полную конфигурацию?
Я понимаю, что ContextLoaderListener следует использовать для загрузки материала, не относящегося к сети, и DispatcherServlet используется для загрузки веб-материала (контроллеров,...). И этот результат в двух контекстах: родительский и дочерний контекст.
Фон:
Я занимался этим стандартным способом в течение нескольких лет.
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:META-INF/spring/applicationContext*.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Handles Spring requests -->
<servlet>
<servlet-name>roo</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>WEB-INF/spring/webmvc-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Это часто вызывало проблемы с двумя контекстами и зависимостями между ними. Раньше я всегда мог найти решение, и у меня есть сильное чувство, что это делает структуру программного обеспечения/архитектуру всегда лучше. Но теперь я столкнулся с проблемой с событиями обоих контекстов.
- Однако это заставляет меня переосмыслить этот два шаблона контекста, и я спрашиваю себя: зачем мне приходить в эту проблему, почему бы не загрузить все конфигурационные файлы spring одним DispatcherServlet
и удалить ContextLoaderListener
полностью. (Я все равно буду иметь разные конфигурационные файлы, но только один контекст.)
Есть ли причина не удалять ContextLoaderListener
?
Ответы
Ответ 1
В вашем случае нет, нет причин держать ContextLoaderListener
и applicationContext.xml
. Если ваше приложение прекрасно работает с контекстом сервлета, то это проще.
Да, общепринятый шаблон заключается в том, чтобы сохранить не-веб-материал в контексте webapp-уровня, но это не более чем слабая конвенция.
Единственные убедительные причины использования контекста webapp-уровня:
- Если у вас есть несколько
DispatcherServlet
, которым необходимо обмениваться услугами
- Если у вас есть устаревшие/не-w760 > сервлеты, которым необходим доступ к Spring -проводным службам
- Если у вас есть фильтры сервлетов, которые подключаются к контексту уровня webapp (например, Spring Безопасность
DelegatingFilterProxy
, OpenEntityManagerInViewFilter
и т.д.)
Ни одно из них не относится к вам, поэтому дополнительная сложность необоснованна.
Просто будьте осторожны при добавлении фоновых задач в контекст сервлета, таких как запланированные задачи, JMS-соединения и т.д. Если вы забудете добавить <load-on-startup>
к вашему web.xml
, то эти задачи не будут запущены до первого доступа сервлета.
Ответ 2
Я хочу поделиться тем, что я сделал в своем приложении Spring -MVC:
-
На we-mvc-config.xml
я добавил только классы, аннотированные с помощью @Controller:
<context:component-scan base-package="com.shunra.vcat">
<context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>
-
В файлах applicationContext.xml
я добавил все остальное:
<context:component-scan base-package="com.shunra.vcat">
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>
Ответ 3
Вы также можете настроить контекст приложения. Например. чтобы сделать работу OpenEntityManagerInViewFilter. Установите ContextLoaderListener, а затем настройте свой DispatcherServlet с помощью:
<servlet>
<servlet-name>spring-mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
</servlet>
Просто убедитесь, что значение параметра contextConfigLocation пусто.