Let's figure out how a Spring MVC web application is configured by analyzing the application artifacts listed in the previous section, Your first Spring MVC application. It contains all the necessary artifacts for building a Spring MVC web app.
The easiest way to create the project structure and the necessary artifacts is using STS to create a Spring MVC project, as described in the previous section. Alternatively, you may use one of the Maven archetypes available in various repositories online. STS uses such a bundled archetype. Here is the typical project structure of a Spring MVC application as viewed in STS:
This structure represents a single-WAR web application where all the services and data access components are collocated with the web controllers. In the case of bigger applications, many such components could be part of a different JAR library project, to be shared between multiple web apps and then added as Maven dependencies to the consuming web apps and beans imported to the web application context XML files using an <import/>
tag or annotation config.
Now, let's examine each artifact listed in Your first Spring MVC application in detail.
The web.xml
file is the standard Java web descriptor in which the fundamental web components that make up a Java web application are registered with the Servlet container. ServletContextListener
, and ServletFilter
components are configured here.
A Spring MVC application is also configured and bootstrapped in web.xml
. ContextLoaderListener
, registered as a ServletContextListener
in the web.xml
sample, bootstraps Spring's root WebApplicationContext
. In the previous chapter, we saw how a simple console application bootstraps the Spring context from inside the main method using ClassPathXmlApplicationContext
. In the case of a web application, following ContextLoaderListener
loads the WebApplicationContext
. Remember, a Spring MVC application is not just another Servlet-based application but rather Spring integrated within a web context.
<listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener>
The following listener looks for a context-param
tag, contextConfigLocation
, which is the location of the Spring root bean definition XML file, as seen in the web.xml
file earlier:
<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/root-context.xml</param-value> </context-param>
The next very important Spring component configured in the web.xml
file is DispatcherServlet
, the centralized entry point into the Spring MVC application which maps every request with appropriate handlers. DispatcherServlet
is an implementation of the Front Controller design pattern, which is a single, centralized entry-point for all HTTP requests that come into the application. This internally delegates them to the actual handler of the request type. Here is an excerpt from the earlier web.xml
listing:
<servlet> <servlet-name>appServlet</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/spring/appServlet/servlet-context.xml </param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>appServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>
The preceding Servlet registration of DispatcherServlet
maps the root URL to DispatcherServlet
so that every HTTP request that comes into the server will be first handled by DispatcherServlet
. Additionally, it specifies where the Spring application context file for this Servlet will be.
A Spring MVC application is nothing but a Servlet-based Web MVC implementation with Spring integrated natively. Hence, it requires Spring bean definitions like any other Spring application, as we have seen in the previous chapter. In the case of a Spring MVC application, there would be some framework-specific beans in addition to application-specific beans registered in the context.
For the sake of organizing beans under different logical categories, such as web-specific (DispatcherServlet
) as well as shared beans, multiple bean definitions can be used. For example, DispatcherServlet
can have its own application context file with beans helping its processing (just for the web context), and there could be a root application context file, where beans that are not specific to the web layer but shared between many layers are defined.
Inside the sample listed in the earlier section as part of Your first Spring MVC application, you can see two Spring bean definition XML files, root-context.xml
and servlet-context.xml
. The root-context.xml
file represents your root WebApplicationContext
loaded via ContextLoaderListener
. This is the place where you define or import your shared beans, such as service beans, and data access objects.
The servlet-context.xml
file is loaded by DispatcherServlet
on startup. The filename, servlet-context.xml
, is an explicit filename given in the sample listing. By default, DispatcherServlet
looks for an XML bean definition file with the pattern [servlet-name]-servlet.xml
, that is, if it wasn't specified explicitly, appServlet
would look for a file with the name appServlet-servlet.xml
at the root of the WEB-INF
folder. Typically, this file contains the bean definitions controlling the behavior of this Servlet. For example, you can see the resources and view resolver bean definitions in the file servlet-context.xml
. You can see that the view resolver configured in the sample listing only supports JSP views.
HomeController
is a simple POJO with the @Controller
annotation. This annotation registers it as a web controller with a set of annotated handler methods inside it. It can have an @RequestMapping
annotation at the class level to indicate the root URL of all handler methods in it. The method home()
is the request handler for the root URL, http://<context-root>/
.
Since the @Controller
annotation is yet another Spring bean, you can inject any other bean into it as a dependency. The sample listing shows that HomeController
has an autowired dependency to TaskService
. In the home()
method, TaskService
methods are invoked, and finally, the return values are set as Model
attributes for the consumption of the latter parts of the request and to be used in a view.
Your application will have many such controllers that serve groups of related URL endpoints; consider HomeController
as your basic example. One controller can have multiple request-handling methods that serve different URLs.
The home.jsp
file is your view artifact for the root (/
) URL. Notice how the Model
attributes are bound inside the JSP view:
<P>There are ${totalOpenTasks}(${totalTasks}) open tasks.</P>
Any request that hits the root URL of the app is first received by DispatcherServlet
, which delegates it to HomeController.home()
, which processes the request and returns the view name (home
, in this case). DispatcherServlet
then picks up the home.jsp
file based on the resource and view configurations specified in servlet-context.xml
and renders it, passing the attributes of the model instance created inside HomeController.home()
.