为什么 DispatcherServlet 会创建另一个应用程序上下文?

2022-09-01 19:12:30

我已经使用 和 上下文 init 参数 配置了根应用程序上下文。ContextLoaderListenercontextConfigLocation

然后由 JSF (*.jsf) 变量解析器访问根上下文。它工作正常。

现在的问题是,通过的请求(*.do)将获得另一个应用程序上下文,然后单例bean被实例化两次。DispatcherServlet

我不需要另一个应用程序上下文,如何指定它来重用现有的根应用程序上下文,该上下文由?DispatcherServletContextLoaderListener

注意

在阅读了答案中的参考页面后,我知道根上下文和调度程序上下文之间存在上下文分离,但是没有一个引用告诉我该去哪里。因此,这是我的解决方案,也许对其他面临类似问题的人有帮助:

  1. 在调度程序 servlet 的上下文配置 XML 中:,我复制了已在根上下文中定义的定义。因此,请将其删除。唯一必须定义仅用于Spring MVC的那些bean。dispatcher-servlet.xml<context:component-scan/>dispatcher-servlet.xml

  2. 所有控制器都已在根上下文中进行扫描和实例化,但是,默认情况下,Spring MVC 不会在根上下文中注册控制器以进行请求映射。您可以:

    2.1. 在根上下文中,从 中排除,并且仅在调度程序 servlet.xml中扫描。@Controller<component-scan>@Controller

    2.2. 或者,将属性设置为 true:DefaultAnnotationHandlerMapping.detectHandlersInAncestorContexts

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

答案 1

为了回答你的第一个问题,DispatcherServlet 创建了一个上下文,因为这就是它允许自己配置的方式,如果你在一个应用程序中有多个 DispatcherServlet,那么它们都需要单独配置。因此,每个都有自己的上下文,并且每个上下文都与“根”上下文分开,其中所有真实的“工作”豆子都应该存在,以便它们可以在其他上下文之间共享。在过去的几周里,由于对这个问题的困惑而产生了许多问题。通过查看答案,您可以更好地了解事情的工作原理:

弹簧 XML 文件配置层次结构帮助/说明

在父上下文与子上下文中声明 Spring Bean

Spring-MVC:什么是“上下文”和“命名空间”?


答案 2

如果您正在运行 DispatcherServlet,则无需使用 ContextLoaderListener。只需使用 ContextLoader.getCurrentWebApplicationContext() 即可访问 WebApplicationContext

只需将豆类定义分开,如前面的答案中所述


推荐