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


373
  • applicationContext.xmlspring-servlet.xml在Spring Framework中相关吗?
  • 声明的属性文件applicationContext.xml是否可用于DispatcherServlet
  • 与此相关的是,为什么我完全需要一个*-servlet.xml?为什么一个applicationContext.xml人不够?

Answers:


430

Spring使您可以在父子层次结构中定义多个上下文。

applicationContext.xml用于“根web应用上下文”,即与该web应用程序相关联的上下文定义了豆。

spring-servlet.xml(或任何你称呼它)定义了一个servlet的应用程序上下文中的豆。一个webapp中可以有很多这样的应用,每个Spring servlet都有一个(例如spring1-servlet.xmlservlet spring1spring2-servlet.xmlservlet spring2)。

中的Bean spring-servlet.xml可以引用中的Bean applicationContext.xml,反之亦然。

所有Spring MVC控制器必须位于spring-servlet.xml上下文中。

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


30
为什么会有多个spring servlet?
NimChimpsky

5
强有力的答案(由于简洁)
两栖游戏,2013年

35
@NimChimpsky有时将应用程序中可能在同一上下文中发生冲突的各个部分分开有时会很有用。作为示例,您可能拥有ReST服务和标准视图,然后您可能对视图具有不同的视图解析器或服务的安全性问题。
Brett Ryan

12
人们在阅读文档和开发应用程序之前应先看到此答案!在正常情况下,根本不需要ContextLoaderListener和contextConfigLocation,仅需要DispatcherServlet!
ruruskyi 2013年

24
在许多教程中,contextConfigLocation包含dispatcher-servlet.xml以及DispatcherServlet。这导致bean被初始化两次!
ruruskyi 2013年

106

场景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" />

从所有四个配置文件test1.xmltest2.xmltest3.xmltest4.xml实例化Bean

结论:在方案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。在FrameworkServletbean中,对springweb进行实例化。在我们的例子中,springweb是FrameworkServlet。

结论:在方案3中,applicationContext DispatcherServlet与之无关。

方案4

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

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。

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


10
+1。很好。我一直在寻找这种类型的比较,但是没有找到。
Ninad Pingale 2014年

@abishkar bhattarai非常好,我的问题是:那么,如果“场景4”时使用@ Component和@Value注释创建bean,那会是什么?
Lawrence

springweb DispatcherServlet如果URL不.action结尾不会叫?
Asif Mushtaq

@lawrence您仍然必须在springweb-servlet.xml中指定类路径,以便Spring可以在其扫描中找到该组件。
veritas

54

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

<!-- 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>

9
为什么呢?为什么不一次扫描整个内容呢?
2012年

3
@NimChimpsky您必须@Controller在servlet上下文中扫描bean(Spring MVC要求)。
Tuukka Mustonen 2012年

3
为什么整个事情不能两次?为什么要包含/排除?
Mike Rylander

8
还应该在spring-servlet.xml中添加use-default-filters =“ false”属性
Rakesh Waghela,2014年

4
Rakesh Waghela指出了。没有该属性,控制器bean将被创建两次。首先在appContext中,其次在ServletContext中
UltraMaster 2014年

12

简单来说

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

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

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


3
我可以在spring-servlet.xml中定义所有bean,但是在这种情况下,应该还有applicationContext.xml可能为空(没有bean)。正确?
Mikhail Kopylov

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作为初始参数提供给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>

4

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.