There are many configuration files required for Spring MVC Project. In pure annotation based Spring MVC Project XML based configurations can be avoided. However XML based configurations are very popular and easy to use. In this article we will try to focus on the various XML Configuration files which will be very helpful in mastering Spring MVC Project.
1. DispatcherServlet
In Spring MVC DispatcherServlet act as front controller. This servlet is configured in web.xml. The minimum configuration for the DispatcherServlet is something like this
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>*.htm</url-pattern> </servlet-mapping> </web-app>
Note:
Notice org.springframework.web.servlet.DispatcherServlet which is named as dispatcher by <servlet-name> tag. So according to default behavior of Spring Framework it will try to load another XML file. The name of that XML is simply adding “-servlet” after the name of the dispatcher servlet. So according to the above configuration in web.xml spring will load dispatcher-servlet.xml file from WEB-INF directory of the project.
Similarly if we name the dispatcher servlet like <servlet-name>foo</servlet-name> then it will try to load foo-servlet.xml.
2. Override the above default behavior of DispatcherServlet
We have seen in the above that spring will load dispatcher-servlet.xml from WEB-INF directory. We can override this default behavior. This can be done by using contextConfigLocation as init parameter of the DispatcherServlet. In the below we are loading foo.xml instead of dispatcher-servlet.xml.
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/foo.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>*.htm</url-pattern> </servlet-mapping> </web-app>
3. Multiple DispatcherServlet in single web.xml
Its also possible to have multiple DispatcherServlet in single web.xml. Here is an example
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"> <servlet> <servlet-name>dispatcher1</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher1</servlet-name> <url-pattern>/app1</url-pattern> </servlet-mapping> <servlet> <servlet-name>dispatcher2</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher2</servlet-name> <url-pattern>/app2</url-pattern> </servlet-mapping> </web-app>
According to the above web.xml, spring will look for two xml files to load. These are dispatcher1-servlet.xml and another is dispatcher2-servlet.xml.
4. WebApplicationContext
As seen in the above that each DispatcherServlet is associated with one XML file. In other words we can say that each DispatcherServlet is associated with single WebApplicationContext. So for a single Spring MVC project we can have multiple WebApplicationContext. In simple language we call those xml file as context files. For dispatcher1 servlet the context file (i.e., in full web application context file) is dispatcher1-servlet.xml. Similarly for dispatcher1 the context file is dispatcher2-servlet.xml.
Remember:
For the controllers under dispatcher1 can access beans from dispatcher1-servlet.xml but not from dispatcher2-servlet.xml and vice versa.
Till now we have seen for each dispatcher servlet there is only one XML file where we define our beans. But in large application we may require beans related to security, service, persistence and so on. So where are we going to define those beans? You may think dispatcher-servlet.xml for this situation. But this is not the good idea. With time the single XML configuration file will become too large and we will end up with poor readability. In this case we can split our bean configuration files into multiple files. For example we can logically divide configuration files like below
xyz-service.xml
xyz-security.xml
xyz-persistance.xml
Note we are free to give any name as we want. These name are just for an example.
6. ContextLoaderListener
To load any bean configuration files along with dispatcher-servlet.xml file we need to configure below listener in web.xml file
org.springframework.web.context.ContextLoaderListener
A sample web.xml with the above listener look like this
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>*.htm</url-pattern> </servlet-mapping> </web-app>
7. Default behavior of ContextLoaderListener
When we mention ContextLoaderListener in web.xml like above it will look for applicationContext.xml file under WEB-INF directory. So according to the above web.xml spring will look two XML file from WEB-INF directory. One dispather-servlet.xml (default file for DispatcherServlet) and another is applicationContext.xml (default file for ContextLoaderListener).
8. Override default behavior of ContextLoaderListener
We can override the default behavior of ContextLoaderListener like DispatcherServlet. See the below example where we are loading applicationContext1.xml instead of default applicationContext.xml.
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext1.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>*.htm</url-pattern> </servlet-mapping> </web-app>
We can also load multiple files like below. Each file should be in new line
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/applicationContext1.xml /WEB-INF/xyz-service.xml /WEB-INF/xyz-security.xml /WEB-INF/xyz-persistance.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>*.htm</url-pattern> </servlet-mapping> </web-app>
Spring loads applicationContext.xml (or many XML files) as discussed above and creates ApplicationContext for the entire application. This is also known as Root Application Context.
Summery
[example title=”Summery:ContextLoaderListener”]
1. Initialize the root application context.
2. Reads a “contextConfigLocation” context-param and passes its value to the context instance, parsing it into potentially multiple file paths which can be separated by any number of commas and spaces, e.g. “WEB-INF/applicationContext1.xml, WEB-INF/applicationContext2.xml”.
3. ContextLoaderListener is optional.We can start Spring application without even configuring ContextLoaderListener and configuring just a basic minimum web.xml with DispatcherServlet.
[/example]
[example title=”Summery:WebApplicationContext”]
1. There can be multiple WebApplicationContext in a single web application.
2. Each DispatcherServlet associated with single WebApplicationContext.
3. Spring will by default load file named “xyz-servlet.xml” from our webapps WEB-INF folder where xyz is the servlet name in web.xml.
4. If we want to change the name of that file name or change the location, add initi-param with contextConfigLocation as param name.
[/example]
[example title=”Summery:ApplicationContext “]
1. applicationContext.xml is the root context configuration for every web application.
2. Spring creates ApplicationContext for the whole application after loading applicationContext.xml file.
3. There will be only one application context per web application.
4. By default Spring search for applicationContext.xml under WEB-INF folder if we don’t use contextConfigLocation param in web.xml
[/example]
[example title=”Relationship between RootApplicationContext and WebApplicationContext”]
Note that ContextLoaderListener loads the specified bean configuration files into the root application context,
while each DispatcherServlet instance loads its configuration file into its own application context and refers to the
root application context as its parent. So, the context loaded by each DispatcherServlet instance can access and
even override beans declared in the root application context (but not vice versa). However, the contexts loaded
by the DispatcherServlet instances cannot access each other.
[/example]