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

【问题讨论】:

标签: java spring


【解决方案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>
    

    【讨论】:

      猜你喜欢
      • 2011-03-30
      • 2012-12-24
      • 2014-04-11
      • 1970-01-01
      • 2014-04-27
      • 1970-01-01
      • 1970-01-01
      • 2015-07-16
      相关资源
      最近更新 更多