了解 Spring MVC 中的上下文

Posted

技术标签:

【中文标题】了解 Spring MVC 中的上下文【英文标题】:Understanding contexts in Spring MVC 【发布时间】:2013-11-06 07:47:37 【问题描述】:

我是 Spring 新手,我正在创建一个简单的 Web 应用程序。我一直在阅读 Spring MVC 中的上下文。

我正在为 Eclipse 使用 STS 插件。我创建了一个 使用该插件的 Spring MVC 项目。

现在我在项目中有三个xml文档,web.xml、root-context.xml和servlet-context.xml。这些是 STS 为我创建的。

    在 web.xml 中,调度程序 servlet 指向 servlet-context.xml,我理解调度程序 servlet 的工作是创建一个知道如何解析视图的 Web 应用程序上下文,并且是控制器 bean 存在的地方. 我的理解正确吗?如果是这样,这个上下文还完成了哪些其他工作?

    现在,有一个名为 root-context.xml 的文件,它对我的​​项目默认包进行了组件扫描。我的理解是这个上下文需要有许多 servlet 可能使用的全局 bean。我的理解正确吗?这还有什么作用?使用此文件创建什么样的上下文?

    现在,我在项目中更进一步,我有几个 *-context.xml 文件(dao-context.xml、security-context.xml 等),这些文件使用 contextLoaderListner(在 web.xml 中)加载.这是一个好主意吗?还是应该将所有内容都放入 servlet-context.xml?我认为拥有不同的上下文是一个好主意,因为它提供了关注点分离。注释?另外,从这些 *-context.xml 文件中创建了什么样的上下文?这些文件的正确文件夹位置是什么?

    Web.xml 用于 servlet 容器,如 tomcat 等,项目中的所有其他 xml 文件用于 spring 容器。那是对的吗?所有这些文件都分开以提供关注点分离?

    当前场景中存在多少个应用上下文和Web应用上下文?

为什么有人需要多个调度器 servlet?

为什么有人需要多个应用程序上下文?

想法?注释?更正?最佳实践?

【问题讨论】:

【参考方案1】:

Spring 不会强迫您以这种方式拥有 xml 文件,您可以只使用一个 servlet-context.xml 的 xml 文件并仅使用调度程序 servlet 来很好地处理所有事情。通常有不同的文件来定义您的服务 bean 或 dao bean,所以这基本上取决于您的应用程序设计,例如,如果您使用的是 spring security,您可能需要添加一个 xml 文件,例如 security-context.xml 之类的正如我所说,这取决于设计。您实际上可以完全消除上下文加载器侦听器,并且仍然可以使用调度程序 servlet 完成所有工作。 您的问题范围太广,因为您是 Spring 新手,您可能应该了解有关 Spring 容器的更多详细信息并决定什么适合您的要求。 我通常在 WEB-INF 中有我的 servlet-context.xml,在类路径中有 service-context.xml 等其他配置,这也不是严格的规则,只是它适合我。

【讨论】:

是的,我知道它是基于设计的。当我按照我解释的方式设计应用程序时,我试图更多地了解创建的实际上下文的术语。例如,调度程序 servlet 创建一个 Web 应用程序上下文,您的 Web 内容应该驻留在其中。上下文加载器侦听器创建应用程序上下文。这两者如何协同工作?是否只有一个应用程序上下文包含 xml 文件中的所有这些 bean,或者为每个 xml 文件创建一个应用程序上下文? 创建的上下文数不依赖于文件数。 DispatcherServlet 被创建为子上下文。 子上下文是什么? 根上下文。您可以根据需要配置任意数量的调度程序 servlet,但始终只有一个根上下文。根上下文中的 bean 可以在所有子上下文中访问。有时我们会配置多个调度器 servlet,例如我们是否可以为我们的休息服务配置另一个调度器 servlet。【参考方案2】:

此设计背后的整个想法是处理典型 Web 应用程序中的不同架构层,并为跨上下文的 bean 提供继承/覆盖机制。 Spring 中每种类型的上下文都与不同的架构层相关,例如 Web 层、服务层等。

基于 Spring 的 Web 应用程序可以配置多个调度程序 servlet(尽管在大多数情况下它是一个 servlet - 但调度程序 serlvet 仍然是一个 servlet,并且可以在 web.xml 中配置多个)。这些可以配置为处理不同的 url 模式。所以显然每个都是不同的 servlet,因此可以有不同的 Spring Web 应用程序上下文。它们中的每一个都可以包含 Spring Web 层的不同配置,例如控制器、拦截器、视图解析器、语言环境解析器等,因为这些通常属于应用程序的 Web 层。所有这些配置和 bean 对每个调度程序 servlet 都是私有的,因此它们彼此不可见。因此,拥有一个单独的 Spring Web 应用程序上下文对于启用这种隐私是有意义的。但是,还有其他设计为共享的 bean,因此属于根上下文。所以所有可共享的东西都属于根上下文,对于这个 Web 应用程序来说,它可以被认为是全局的。

每个调度程序 servlet 都继承了根上下文中定义的所有 bean。然而,需要注意的重要一点是,共享的 bean 可以被各自的调度程序 servlet 特定的 bean 覆盖。因此,在 Web 应用程序中,根上下文可以被视为可以被继承但可以被覆盖的东西。

【讨论】:

谢谢。我想我开始明白了。根应用程序上下文与每个 xml 文件中定义的上下文有何不同(或相关)? 在 Web 应用程序中,通常使用 ContextLoaderListener 初始化的根上下文将根上下文存储在名为 WebApplicationContext.class.getName() + ".ROOT" 的 Servlet 上下文(应用程序范围)变量中,此后每个调度程序 serlvet(或任何代码)如果可以访问 servlet 上下文,则可以在内部访问此属性 知道了!那么这些 xml 文件,dao-context.xml service-context.xml 是创建更多的上下文还是只是添加到 contextLoaderListener 创建的根上下文中?这些 xml 文件的范围是什么? 您可以提供单个 xml 文件并在 xml 文件中使用 import 标记来导入不同的上下文文件,如 dao-context.xml 或者您可以提供逗号分隔的不同 xml 文件,或使用类路径前缀 -这是一个选择问题。但是,所有这些都将在单个根上下文中。在这种情况下使用不同的 xml 文件通常只是从模块化和关注点分离的角度来看。 你也可以在这里找到很好的解释,link

以上是关于了解 Spring MVC 中的上下文的主要内容,如果未能解决你的问题,请参考以下文章

Spring MVC 中的不同上下文是如何工作的?

Spring MVC 了解WebApplicationContext中特殊的bean类型

Spring MVC3 资源正在加载,包括上下文中的 requestMapping 值

Spring-MVC理解之一:应用上下文webApplicationContext

Spring MVC + Thymeleaf:将变量添加到所有模板的上下文中

为啥 Spring MVC 至少需要两个上下文?