简体   繁体   English

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

[英]Order of loading contextConfigLocation in web.xml of Spring Servlet project

Suppose that I have a Spring Java project and I am trying to configure it as a web server servlet. 假设我有一个Spring Java项目,我正在尝试将其配置为Web服务器servlet。 Here is a stripped-down version of the web.xml file: 这是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>

The key thing to note here is that I have specified two XML files to be loaded. 这里要注意的关键是我已经指定了两个要加载的XML文件。 One is general for my entire application, while the other is specific to the "my-servlet" servlet. 一个是我的整个应用程序的通用,而另一个是特定于“my-servlet”servlet。 For a setup with just one servlet-mapping, this wouldn't make sense. 对于只有一个servlet映射的设置,这没有意义。 However, my project has multiple servlet-mappings and each one has specific Spring settings to them. 但是,我的项目有多个servlet映射,每个都有特定的Spring设置。

My Question: Which contextConfigLocation is going to be loaded first by Spring? 我的问题: Spring将首先加载哪个contextConfigLocation? Will it be the generalApplicationContext.xml or will it be the specificApplicationContext.xml? 它是generalApplicationContext.xml还是specialApplicationContext.xml? More importantly, does the order of loading even matter? 更重要的是,装载的顺序是否重要? From my debugging efforts, it seems apparent that it does because I get different errors when I move some independent Spring configuration from one file to the other. 从我的调试工作来看,它似乎很明显,因为当我将一些独立的Spring配置从一个文件移动到另一个文件时,我得到了不同的错误。

NB: Whether or not using multiple spring configurations for multiple servlet mappings is a good practice is debatable. 注意:对于多个servlet映射是否使用多个弹簧配置是一个好的做法是值得商榷的。 Same goes for using XML config instead of the new Java config. 使用XML配置而不是新的Java配置也是如此。 But that's not what I'm trying to ask here. 但这不是我在这里要问的问题。 Let's try to focus on my main question. 让我们试着关注我的主要问题。

generalApplicationContext.xml is the one that will be loaded first because it is the ApplicationContext loaded with the ContextLoaderListener generalApplicationContext.xml是首先加载的,因为它是使用ContextLoaderListener加载的ApplicationContext

<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 is actually a Child Context of the Above loaded generalApplicationContext.xml and it will be a WebApplicationContext 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>

And yes the order of loading does matter. 是的,加载顺序很重要。 Because when the parent context is loaded all the required dependencies must be fulfilled. 因为在加载父上下文时,必须满足所有必需的依赖项。

The below part loads the context file and create the ApplicationContext . 下面的部分加载上下文文件并创建ApplicationContext This context might, for instance, contain components such as middle-tier transactional services, data access objects, or other objects that you might want to use (and re-use) across the application. 例如,此上下文可能包含组件,例如中间层事务服务,数据访问对象或您可能希望在整个应用程序中使用(和重用)的其他对象。 There will be one application context per application. 每个应用程序将有一个应用程序上下文。

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

The other context is the WebApplicationContext which is the child context of the application context . 另一个上下文是WebApplicationContext ,它是应用程序上下文子上下文 Each DispatcherServlet defined in a Spring web application will have an associated WebApplicationContext . Spring Web应用程序中定义的每个DispatcherServlet都有一个关联的WebApplicationContext The initialization of the WebApplicationContext happens like this: 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>

For more details refer this and this 有关详细信息,请参阅

What better way to actually have the Spring debug logs tell you itself the order. 实际拥有Spring调试日志的更好方法是告诉您自己的顺序。 If you want to get into the code you can also take a look at the org.springframework.web.servlet.FrameworkServlet ( DispatcherServlet extends this class) Just enable the logger "org.springframework.web.servlet" to debug level in your preferred logging framework 如果你想进入代码,你也可以看一下org.springframework.web.servlet.FrameworkServletDispatcherServlet扩展这个类)只需启用logger "org.springframework.web.servlet"来调试你喜欢的级别记录框架

Here is how the logs would typically look like - clearly the root context is loaded first and is set as the parent for the context heirarchy - the servlet context is loaded next. 以下是日志通常的样子 - 显然首先加载根上下文并将其设置为上下文层次结构的父上下文 - 接下来加载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

If you are having ContextLoaderListener in your web.xml spring will load the generalApplicationContext.xml first. 如果您在web.xml中使用ContextLoaderListener ,则spring将首先加载generalApplicationContext.xml This will create beans and provide them all Servlets and Filters. 这将创建bean并为它们提供所有Servlet和过滤器。 This xml should have the common classes, beans which are used in your application. 这个xml应该有你的应用程序中使用的公共类bean。

Later spring container will load the specificApplicationContext.xml , because you have load on startup in the servlet config. 后来的spring容器将加载specificApplicationContext.xml ,因为你在servlet配置中启动时加载了。 If you don't specify the load on start up, this specificApplicationContext.xml will load when the first request comes to your application with the specific url-pattern. 如果未在启动时指定负载,则在第一个请求带有特定url-pattern的应用程序时,将加载此specificApplicationContext.xml

As your question when you move you springconfig from one config to another this will change the application resource availability to the container. 正如您将springconfig从一个配置移动到另一个配置时的问题,这将改变容器的应用程序资源可用性。 If you specify the Controller beans in generalApplicationContext.xml and you don't specify them in specificApplicationContext.xml then your DispatcherServlet wont find the mappings, so you will see 404 error. 如果在generalApplicationContext.xml中指定Controller bean,并且未在specificApplicationContext.xml中指定它们,则DispatcherServlet将找不到映射,因此您将看到404错误。

If you want to create some bean objects on-demand you can create one more servlet-config to load that specific specificConfigurationFile2.xml, and map to the url-pattern. 如果要按需创建一些bean对象,可以再创建一个servlet-config来加载特定的specificConfigurationFile2.xml,并映射到url-pattern。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM