Подтвердить что ты не робот

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

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

После этого корневой контекст получает доступ к JSF (*.jsf) variable-resolver. Он отлично работает.

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

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

Примечание

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

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

  • Все контроллеры уже были проверены и созданы в корневом контексте, однако Spring MVC по умолчанию не регистрирует контроллеры в корневом контексте для сопоставлений запросов. Вы можете:

    2,1. В корневом контексте исключите @Controller из <component-scan> и сканируйте @Controller только в dispatcher-servlet.xml.

    2,2. Или установите для свойства DefaultAnnotationHandlerMapping.detectHandlersInAncestorContexts значение true:

    (dispatcher-servlet.xml:)
    
    <bean id="handlerMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
        <property name="detectHandlersInAncestorContexts" value="true" />
    </bean>
    
4b9b3361

Ответ 1

Чтобы ответить на ваш первый вопрос, DispatcherServlet создает контекст, потому что он позволяет настроить его, и если у вас несколько DispatcherServlets в одном приложении, каждый из них должен быть настроен отдельно. Поэтому каждый из них получает свой собственный контекст, и каждый из этих контекстов отделен от "корневого" контекста, где должен работать весь ваш настоящий "рабочий" beans, чтобы они могли делиться между другими контекстами. За последние пару недель был задан ряд вопросов, порожденных путаницей по этой самой проблеме. Вы могли бы лучше понять, как все работает, проверяя ответы:

Spring Справка/объяснение иерархии файлов XML

Объявление Spring Bean в контексте родительского контекста и дочернего контекста

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

Ответ 2

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

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