Spring Framework中applicationContext.xml和spring-servlet.xml的区别

Posted

技术标签:

【中文标题】Spring Framework中applicationContext.xml和spring-servlet.xml的区别【英文标题】:Difference between applicationContext.xml and spring-servlet.xml in Spring Framework 【发布时间】:2011-04-08 19:14:27 【问题描述】: applicationContext.xmlspring-servlet.xml 在 Spring Framework 中是否相关? applicationContext.xml 中声明的属性文件是否可用于DispatcherServlet? 在相关说明中,我为什么需要*-servlet.xml?为什么单独applicationContext.xml 不够?

【问题讨论】:

也可以看到这个。 ***.com/questions/11708967/… 【参考方案1】:

Spring 允许您在父子层次结构中定义多个上下文。

applicationContext.xml 定义了“根 webapp 上下文”的 bean,即与 webapp 关联的上下文。

spring-servlet.xml(或任何其他名称)为一个 servlet 的应用程序上下文定义了 bean。在一个 web 应用程序中可以有许多这些,每个 Spring servlet 一个(例如,spring1-servlet.xml 用于 servlet spring1spring2-servlet.xml 用于 servlet spring2)。

spring-servlet.xml 中的 Bean 可以引用 applicationContext.xml 中的 bean,反之则不行。

所有 Spring MVC 控制器都必须进入 spring-servlet.xml 上下文。

在大多数简单的情况下,applicationContext.xml 上下文是不必要的。它通常用于包含在 webapp 中的所有 servlet 之间共享的 bean。如果您只有一个 servlet,那么没有什么意义,除非您对它有特定用途。

【讨论】:

为什么会有多个 spring servlet? 强大有力的答案(因为简洁) @NimChimpsky 有时将应用程序中可能在同一上下文中发生冲突的部分分开很有用。例如,您可能有 ReST 服务和标准视图,然后您可能对视图有不同的视图解析器或服务的安全问题。 人们应该在阅读文档和开发应用程序之前看到这个答案!在正常情况下,根本不需要 ContextLoaderListener 和 contextConfigLocation,只需 DispatcherServlet! 在许多教程中,contextConfigLocation 包含 dispatcher-servlet.xml 以及 DispatcherServlet。这会导致 bean 被初始化两次!【参考方案2】:

我还要补充一点。在spring-servlet.xml 中,我们包括对控制器包的组件扫描。 在下面的示例中,我们包含控制器包的过滤器注释。

<!-- Scans for annotated @Controllers in the classpath -->
<context:component-scan base-package="org.test.web" use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

applicationcontext.xml 中,我们为除控制器之外的剩余包添加过滤器。

<context:component-scan base-package="org.test">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

【讨论】:

为什么?为什么不一次扫描整个东西? @NimChimpsky 您必须在 servlet 上下文中扫描 @Controller bean(Spring MVC 需要)。 为什么不能整件事两次呢?为什么包含/排除? 还应该在 spring-servlet.xml 中添加 use-default-filters="false" 属性 Rakesh Waghela 有观点。如果没有该属性,Controller bean 将被创建两次。首先在 appContext 中,然后在 servletContext 中【参考方案3】:

场景 1

在客户端应用程序中(应用程序不是 Web 应用程序,例如可能是 Swing 应用程序)

private static ApplicationContext context = new  ClassPathXmlApplicationContext("test-client.xml");

context.getBean(name);

不需要 web.xml。 ApplicationContext 作为获取 bean 服务的容器。不需要 Web 服务器容器。 在 test-client.xml 中可以有没有远程处理的简单 bean,有远程处理的 bean。

结论:在场景 1 中 applicationContext 和 DispatcherServlet 不相关。

场景 2

在服务器应用程序中(部署在服务器中的应用程序,例如 Tomcat)。通过客户端程序(例如 Swing 应用程序)远程访问服务

web.xml中定义监听器

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

在服务器启动时ContextLoaderListener 实例化 applicationContext.xml 中定义的 bean。

假设您在 applicationContext.xml 中定义了以下内容:

<import resource="test1.xml" />
<import resource="test2.xml" />
<import resource="test3.xml" />
<import resource="test4.xml" />

bean 是从所有四个配置文件 test1.xmltest2.xmltest3.xmltest4 中实例化的。 xml.

结论:在场景2中applicationContext和DispatcherServlet不相关。

场景 3

在带有 Spring MVC 的 Web 应用程序中。

web.xml 中定义:

<servlet>
    <servlet-name>springweb</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>    
</servlet>

<servlet-mapping>
    <servlet-name>springweb</servlet-name>
    <url-pattern>*.action</url-pattern>
</servlet-mapping>

当 Tomcat 启动时,springweb-servlet.xml 中定义的 bean 被实例化。 DispatcherServlet 扩展了 FrameworkServlet。在 FrameworkServlet bean 实例化发生在 springweb 中。在我们的例子中 springweb 是 FrameworkServlet。

结论:在场景3中applicationContext和DispatcherServlet不相关。

场景 4

在带有 Spring MVC 的 Web 应用程序中。 springweb-servlet.xml 用于 servlet 和 applicationContext.xml 用于访问服务器程序中的业务服务或访问另一个服务器程序中的 DB 服务。

web.xml 中定义了以下内容:

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
    <servlet-name>springweb</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>        
</servlet>

<servlet-mapping>
    <servlet-name>springweb</servlet-name>
    <url-pattern>*.action</url-pattern>
</servlet-mapping>

在服务器启动时,ContextLoaderListener 实例化 applicationContext.xml 中定义的 bean;假设您已在此声明:

<import resource="test1.xml" />
<import resource="test2.xml" />
<import resource="test3.xml" />
<import resource="test4.xml" />

bean 都是从所有四个 test1.xmltest2.xmltest3.xmltest4.xml 实例化的applicationContext.xml中定义的bean实例化完成后,springweb-servlet.xml中定义的bean被实例化。

所以实例化顺序是:根(应用程序上下文),然后是 FrameworkServlet。

现在应该清楚为什么它们在哪种情况下很重要。

【讨论】:

+1。非常好。我一直在寻找这种类型的比较,但从未找到。 @abishkar bhattarai 很好,我的问题是:那么如果在“场景4”时使用@Component 和@Value 注解创建bean 会怎样 springweb DispatcherServlet 如果 url 不以 .action 结尾,则不会调用? @lawrence 您仍然必须在 springweb-servlet.xml 中指定类路径,以便 Spring 可以在其扫描中找到该组件。【参考方案4】:

应用程序上下文提供了一种解析文本消息的方法,包括对这些消息的 i18n 的支持。 应用程序上下文提供了一种加载文件资源(例如图像)的通用方法。 应用程序上下文可以将事件发布到注册为侦听器的 bean。 容器或容器中的 bean 上的某些操作,必须通过 bean 工厂以编程方式处理,可以在应用程序上下文中以声明方式处理。 ResourceLoader 支持:Spring 的 Resource 接口使用灵活的通用抽象来处理低级资源。应用程序上下文本身是一个 ResourceLoader,因此为应用程序提供了对特定于部署的资源实例的访问权限。 MessageSource 支持:应用上下文实现 MessageSource,一个用于获取本地化消息的接口,实际实现是可插拔的

【讨论】:

【参考方案5】:

简单来说,

applicationContext.xml 定义在所有 servlet 之间共享的 bean。如果您的应用程序有多个 servlet,那么在 applicationContext.xml 中定义公共资源会更有意义。

spring-servlet.xml 定义仅与该 servlet 相关的 bean。这里是调度程序 servlet。所以,你的 Spring MVC 控制器必须在这个文件中定义。

如果您在 Web 应用程序中只运行一个 servlet,那么在 spring-servlet.xml 中定义所有 bean 并没有错。

【讨论】:

我可以在 spring-servlet.xml 中定义所有的 bean,但在这种情况下也应该有可能是空的 applicationContext.xml(没有 bean)。对吗?【参考方案6】:

在 Servlet 技术中,如果您想将任何输入传递给特定的 servlet,那么您需要像下面的代码一样传入 init 参数。

 <servlet>
    <servlet-name>DBController</servlet-name>
    <servlet-class>com.test.controller.DBController</servlet-class>
    <init-param>
        <param-name>username</param-name>
        <param-value>John</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>DBController</servlet-name>
    <url-pattern>/DBController</url-pattern>
</servlet-mapping>

如果你想传递一些对所有 servlet 通用的输入,那么你需要配置上下文参数。示例

 <context-param>
    <param-name>email</param-name>
    <param-value>admin@example.com</param-value>
</context-param>

当我们使用 Spring MVC 时,就像这样,我们需要通过 init 参数向 Spring 提供的预定义 servlet 提供一些信息,即 DispatcherServlet。 所以配置是休闲的,这里我们将 spring-servlet.xml 作为 init 参数提供给 DispatcherServlet。

 <?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
              http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
    <display-name>Spring MVC App</display-name>

    <servlet>
        <servlet-name>SpringController</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>SpringController</servlet-name>
        <url-pattern>*.htm</url-pattern>
    </servlet-mapping>
</web-app>

我们再次需要一些上下文参数。这适用于整个应用程序。 所以我们可以提供根上下文,即 applicationcontext.xml 配置是这样的:

    <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationcontext.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
        <servlet-name>SpringController</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>SpringController</servlet-name>
        <url-pattern>*.htm</url-pattern>
    </servlet-mapping>

【讨论】:

以上是关于Spring Framework中applicationContext.xml和spring-servlet.xml的区别的主要内容,如果未能解决你的问题,请参考以下文章

Spring ioc基础内容

Spring Framework 组件注册 之 @Import

spring json 返回中文乱码

如何在 Eclipse 中查看 Spring Framework Javadoc?

Spring Framework,Spring Security - 可以在没有 Spring Framework 的情况下使用 Spring Security?

Spring Framework中applicationContext.xml和spring-servlet.xml的区别