Почему DispatcherServlet создает другой контекст приложения?
Я настроил контекст корневого приложения, используя ContextLoaderListener
и контекстный параметр init contextConfigLocation
,
Затем к корневому контексту обращается переменная-преобразователь JSF (*.jsf). Работает нормально.
Теперь проблема в том, что запросы (*.do) проходят через DispatcherServlet
получит другой контекст приложения, а затем синглтон-бины будут созданы дважды.
Мне не нужен другой контекст приложения для DispatcherServlet
Как я могу указать его для повторного использования существующего корневого контекста приложения, который загружается ContextLoaderListener
?
НОТА
После прочтения справочных страниц в ответах я знаю, что между корневым контекстом и контекстом диспетчера существует разделение контекста, но ни одна из ссылок не говорит мне, куда идти. Итак, вот мое решение, может быть, полезно для других людей, сталкивающихся с подобным вопросом:
В контексте конфигурации XML для сервлета диспетчера:
dispatcher-servlet.xml
Я продублировал<context:component-scan/>
который уже определен в корневом контексте. Так что убери это.dispatcher-servlet.xml
нужно определить только те компоненты, которые используются только для Spring MVC.Все контроллеры уже были отсканированы и созданы в корневом контексте, однако Spring MVC по умолчанию не регистрирует контроллеры в корневом контексте для сопоставления запросов. Вы также можете:
2.1. В корневом контексте исключить
@Controller
от<component-scan>
и сканировать@Controller
только в dispatcher-servlet.xml.2.2. Или установите свойство
DefaultAnnotationHandlerMapping.detectHandlersInAncestorContexts
к истине:(dispatcher-servlet.xml:) <bean id="handlerMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> <property name="detectHandlersInAncestorContexts" value="true" /> </bean>
2 ответа
Чтобы ответить на ваш первый вопрос, DispatcherServlet создает контекст, потому что именно так он позволяет себя настраивать, и если у вас есть несколько DispatcherServlet в одном приложении, каждый из них должен быть настроен отдельно. Поэтому каждый получает свой собственный контекст, и каждый из этих контекстов отделен от "корневого" контекста, где должны жить все ваши реальные, "рабочие" бины, чтобы они могли быть разделены между другими контекстами. За последние пару недель было несколько вопросов, которые возникли из-за неразберихи по поводу этой самой проблемы. Вы можете лучше понять, как все работает, проверив ответы:
Справка / объяснение иерархии конфигурации файлов Spring XML
Объявление Spring Bean в родительском контексте против дочернего контекста
Если у тебя есть DispatcherServlet
работает, нет необходимости использовать ContextLoaderListener
, Просто используйте ContextLoader.getCurrentWebApplicationContext()
чтобы получить доступ к WebApplicationContext
,
Просто держите определения компонентов отдельно, как указано в предыдущем ответе.