根上下文和调度程序 servlet 上下文到底是如何进入 Spring MVC Web 应用程序的?

Posted

技术标签:

【中文标题】根上下文和调度程序 servlet 上下文到底是如何进入 Spring MVC Web 应用程序的?【英文标题】:How exactly are the root context and the dispatcher servlet context into a Spring MVC web application? 【发布时间】:2015-08-18 19:53:22 【问题描述】:

我正在学习Spring MVC,我有一些疑问

所以,我有这个配置类来配置处理用户请求的 DispatcherServlet

public class MyWebAppInitializer implements WebApplicationInitializer 

    @Override
    public void onStartup(ServletContext container) 

        // Create the 'root' Spring application context
        AnnotationConfigWebApplicationContext rootContext = ...
        // Create the dispatcher servlet's Spring application context
        AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();

       dispatcherContext.register(DispatcherConfig.class);

       // Register and map the dispatcher servlet
       ServletRegistration.Dynamic dispatcher = container.addServlet("main", new DispatcherServlet(dispatcherContext));
       dispatcher.setLoadOnStartup(1);
       dispatcher.addMapping("main/");
   

DispatcherServlet 的工作原理对我来说非常清楚。我的疑问与 context 概念有关。

1) 上下文究竟代表什么?我认为这就像一组具有特定用途的豆子,并且可以在环境中协同工作。但我对这个断言绝对不正确。

2) 根上下文dispatcher servlet上下文有什么区别?

3) 据我了解,dispatcherContext 中定义的 bean 可以访问 rootContext 中定义的 bean(但反之则不然)。为什么?

Tnx

【问题讨论】:

你的 WAR 文件就是上下文。 ContextLoaderListener 加载的 Beans/configuraiton 是根上下文,DispatcherServlet(或 Spring-WS 的 MessageDispatcherServlet)加载的所有内容都是子上下文。您可以拥有多个 servlet,它们都可以访问根上下文(应该包含共享资源,如服务等)。现在,如果您有 10 个调度程序 servlet,根上下文应该访问哪个 servlet?因此,只有父母可以从孩子那里访问,而不是相反。这也会导致 AOP 出现问题,突然间,子级定义的 AOP 会影响父级。 @M.Deinum Tnx 这么多,完美的解释。如果你把它作为回应我会接受它:-) ***.com/questions/19619539/… link1 , link2 有很好的解释。 【参考方案1】:

根上下文

Spring 应用程序中的根上下文是由ContextLoaderListener 加载的ApplicationContext。此上下文应具有全球可用的资源,如服务、存储库、基础设施 bean(DataSourceEntityManagerFactorys 等)等。

ContextLoaderListener 在名称 org.springframework.web.context.WebApplicationContext.ROOT 下的 ServletContext 中注册此上下文。

如果您自己加载一个ApplicationContext 并在ServletContext 中使用上面的名称注册它,那么它将成为根上下文。

子上下文

Spring 应用程序中的子上下文是由DispatcherServlet 加载的ApplicationContext(或者例如Spring-WS 应用程序中的MessageDispatcherServlet)。此上下文应仅包含与该上下文相关的 bean,对于 Spring MVC,应为 ViewResolvers、HandlerMappings 等。

servlet 在名称 org.springframework.web.servlet.FrameworkServlet.CONTEXT.<servlet-name> 下的 ServletContext 中注册此上下文。

只有子上下文可以访问父上下文,因为您可以有多个子上下文。例如在 Spring MVC 中结合 Spring WS 应用程序。父上下文由子级通过在具有众所周知的名称的ServletContext 中找到它来检测。

如果根上下文可以访问子上下文,它将使用哪一个来连接 bean?除此之外,如果是这种情况,当涉及 AOP 时,您也会得到令人惊讶的结果。在子上下文中定义的 AOP 会突然影响在根上下文中配置的 bean。

【讨论】:

太棒了!,非常简洁的解释。 您能否提供任何示例如何实现 1 个根上下文和 2 个子上下文? 答案中已经提到过,例如 Spring MVC 和 Spring WS 的结合。但是,也没有什么可以阻止您创建多个 DispatcherServlet 实例。

以上是关于根上下文和调度程序 servlet 上下文到底是如何进入 Spring MVC Web 应用程序的?的主要内容,如果未能解决你的问题,请参考以下文章

在 Spring Boot 中使用多个调度程序 Servlet/Web 上下文

在根和子应用程序上下文中具有相同名称的 Bean?

Spring MVC 调度程序 xml 和应用程序上下文 xml

如何从 servlet 上下文而不是根上下文中获取 bean?

无法过滤上下文根 Servlet 请求

不理解 Java EE 中上下文的概念