Почему DispatcherServlet создает другой контекст приложения?

Я настроил контекст корневого приложения, используя ContextLoaderListener и контекстный параметр init contextConfigLocation,

Затем к корневому контексту обращается переменная-преобразователь JSF (*.jsf). Работает нормально.

Теперь проблема в том, что запросы (*.do) проходят через DispatcherServlet получит другой контекст приложения, а затем синглтон-бины будут созданы дважды.

Мне не нужен другой контекст приложения для DispatcherServletКак я могу указать его для повторного использования существующего корневого контекста приложения, который загружается ContextLoaderListener?

НОТА

После прочтения справочных страниц в ответах я знаю, что между корневым контекстом и контекстом диспетчера существует разделение контекста, но ни одна из ссылок не говорит мне, куда идти. Итак, вот мое решение, может быть, полезно для других людей, сталкивающихся с подобным вопросом:

  1. В контексте конфигурации XML для сервлета диспетчера: dispatcher-servlet.xmlЯ продублировал <context:component-scan/> который уже определен в корневом контексте. Так что убери это. dispatcher-servlet.xml нужно определить только те компоненты, которые используются только для Spring MVC.

  2. Все контроллеры уже были отсканированы и созданы в корневом контексте, однако 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 в родительском контексте против дочернего контекста

Spring-MVC: что такое "контекст" и "пространство имен"?

Если у тебя есть DispatcherServlet работает, нет необходимости использовать ContextLoaderListener , Просто используйте ContextLoader.getCurrentWebApplicationContext() чтобы получить доступ к WebApplicationContext ,

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

Другие вопросы по тегам