简体   繁体   中英

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. Here is a stripped-down version of the web.xml file:

<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. One is general for my entire application, while the other is specific to the "my-servlet" servlet. For a setup with just one servlet-mapping, this wouldn't make sense. However, my project has multiple servlet-mappings and each one has specific Spring settings to them.

My Question: Which contextConfigLocation is going to be loaded first by Spring? Will it be the generalApplicationContext.xml or will it be the specificApplicationContext.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.

NB: Whether or not using multiple spring configurations for multiple servlet mappings is a good practice is debatable. Same goes for using XML config instead of the new Java config. 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

<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

<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 . 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 . Each DispatcherServlet defined in a Spring web application will have an associated WebApplicationContext . The initialization of the WebApplicationContext happens like this:

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

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.

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. This will create beans and provide them all Servlets and Filters. This xml should have the common classes, beans which are used in your application.

Later spring container will load the specificApplicationContext.xml , because you have load on startup in the servlet config. 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.

As your question when you move you springconfig from one config to another this will change the application resource availability to the container. 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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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