在Spring Servlet项目的web.xml中加载contextConfigLocation的顺序

时间:2014-12-18 05:09:38

标签: java spring spring-mvc servlets web.xml

假设我有一个 Spring Java 项目,我正在尝试将其配置为Web服务器servlet。以下是 web.xml 文件的精简版:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/spring/generalApplicationContext.xml
    </param-value>
</context-param>

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

<servlet-mapping>
    <servlet-name>my-servlet</servlet-name>
    <url-pattern>/foo/*</url-pattern>
</servlet-mapping>

这里需要注意的关键是我已经指定了两个要加载的XML文件。一个是我的整个应用程序的通用,而另一个是特定于&#34; my-servlet&#34; servlet的。对于只有一个servlet映射的设置,这没有意义。但是,我的项目有多个servlet映射,每个都有特定的Spring设置。

我的问题: Spring会首先加载哪个contextConfigLocation?它是generalApplicationContext.xml还是specialApplicationContext.xml?更重要的是,装载的顺序是否重要?从我的调试工作来看,它似乎很明显,因为当我将一些独立的Spring配置从一个文件移动到另一个文件时,我得到了不同的错误。

NB:对于多个servlet映射是否使用多个弹簧配置是一个很好的做法值得商榷。使用XML配置而不是新的Java配置也是如此。但这不是我在这里要问的问题。让我们试着关注我的主要问题。

4 个答案:

答案 0 :(得分:21)

generalApplicationContext.xml是首先加载的,因为ApplicationContext加载了ContextLoaderListener

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

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/spring/generalApplicationContext.xml
    </param-value>
</context-param>

specificApplicationContext.xml实际上是上面加载的generalApplicationContext.xml的子上下文,它将是WebApplicationContext

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

<servlet-mapping>
    <servlet-name>my-servlet</servlet-name>
    <url-pattern>/foo/*</url-pattern>
</servlet-mapping>

是的,加载顺序很重要。因为在加载父上下文时,必须满足所有必需的依赖项。

答案 1 :(得分:8)

以下部分加载上下文文件并创建 ApplicationContext 。例如,此上下文可能包含组件,例如中间层事务服务,数据访问对象或您可能希望在整个应用程序中使用(和重用)的其他对象。每个应用程序将有一个应用程序上下文。

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/spring/generalApplicationContext.xml
    </param-value>
</context-param>

另一个上下文是 WebApplicationContext ,它是应用程序上下文的子上下文。 Spring Web应用程序中定义的每个DispatcherServlet都有一个关联的WebApplicationContextWebApplicationContext的初始化发生如下:

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

有关详细信息,请参阅thisthis

答案 2 :(得分:7)

实际拥有Spring调试日志的更好方法是告诉您自己的顺序。 如果你想进入代码,你也可以看一下org.springframework.web.servlet.FrameworkServletDispatcherServlet扩展这个类)只需在你首选的日志框架中启用logger "org.springframework.web.servlet"调试级别

以下是日志通常的样子 - 显然首先加载根上下文并将其设置为上下文层次结构的父级 - 接下来加载servlet上下文。

INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from ServletContext resource [/WEB-INF/spring/generalApplicatonContext.xml]
INFO : org.springframework.web.context.ContextLoader - Root WebApplicationContext: initialization completed in 256 ms
DEBUG: org.springframework.web.servlet.DispatcherServlet - Initializing servlet 'my-servlet'
INFO :Initializing Spring FrameworkServlet 'appServlet'
INFO : org.springframework.web.servlet.DispatcherServlet - FrameworkServlet 'my-servlet': initialization started
DEBUG: org.springframework.web.servlet.DispatcherServlet - Servlet with name 'appServlet' will try to create custom WebApplicationContext context of class 'org.springframework.web.context.support.XmlWebApplicationContext', using parent context [Root WebApplicationContext: startup date [Fri May 15 17:08:24 IST 2015]; root of context hierarchy
DEBUG: Loading XML bean definitions from ServletContext resource [/WEB-INF/spring/specificApplicationContext.xml

答案 3 :(得分:3)

如果您在web.xml中有 ContextLoaderListener ,那么Spring将首先加载 generalApplicationContext.xml 。这将创建bean并为它们提供所有Servlet和过滤器。这个xml应该有你的应用程序中使用的公共类bean。

以后的spring容器将加载 specificApplicationContext.xml ,因为您在servlet配置中启动时加载。如果您未在启动时指定负载,则 specificApplicationContext.xml 将在第一个请求带到特定网址模式的应用程序时加载。< / p>

当您将springconfig从一个配置移动到另一个配置时,这是一个问题,这将改变容器的应用程序资源可用性。如果在generalApplicationContext.xml中指定Controller bean,并且您没有在specificApplicationContext.xml中指定它们,那么DispatcherServlet将找不到映射,因此您将看到404错误。

如果要按需创建一些bean对象,可以再创建一个servlet-config来加载特定的specificConfigurationFile2.xml,并映射到url-pattern。