Getting Started with Spring MVC


Spring MVC, a part of the core Spring Framework, is a mature and capable action-response style web framework, with a wide range of capabilities and options aimed at handling a variety of UI-focused and non-UI-focused web tier use cases. All this can potentially be overwhelming to the Spring MVC neophyte. I think it's useful for this audience to show just how little work there is to get a bare Spring MVC application up and running (i.e. consider my example something akin to the world's simplest Spring MVC application), and that's what I'll spend the rest of this article demonstrating.
I'm assuming you are familiar with Java, Spring (basic dependency injection concepts), and the basic Servlet programming model, but do not know Spring MVC. After reading this blog entry, readers may continue learning about Spring MVC by looking at Keith Donald's Spring MVC 3 Showcase, or the variety of other online and print resources available that cover Spring and Spring MVC.
Spring MVC includes most of the same basic concepts as other so-called web MVC frameworks. Incoming requests enter the framework via a Front Controller. In the case of Spring MVC, this is an actual Java Servlet called DispatcherServlet. Think of DispatcherServlet as the gatekeeper. It doesn't perform any real web or business logic, but rather delegates to POJOs called Controllers where the real work is done (either in whole or via the back-end). When the work has been done, it's the responsibility of Views to produce the output in the proper format (whether that's a JSP page, Velocity template, or JSON response). Strategies are used to decide which Controller (and which method(s) inside that Controller) handles the request, and which View renders the response. The Spring container is used to wire together all these pieces. It all looks something like this:



DispatcherServlet and Spring Container

As mentioned, all incoming requests flow through a DispatcherServlet. Like any other Servlet in a Java EE application, we tell the Java EE container to load this Servlet at web app startup time via an in the web app's WEB-INF/web.xml. TheDispatcherServlet is also responsible for loading a Spring ApplicationContext that is used to perform wiring and dependency injection of managed component. On this basis, we specify some init parameters to the Servlet which configure the Application Context. Let's look at the config in web.xml:
WEB-INF/web.xml
01<?xml version="1.0" encoding="UTF-8"?>
02<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
05 
06    <!-- Processes application requests -->
07    <servlet>
08        <servlet-name>appServlet</servlet-name>
09        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
10        <init-param>
11            <param-name>contextConfigLocation</param-name>
12            <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
13        </init-param>
14        <load-on-startup>1</load-on-startup>
15    </servlet>       
16 
17    <servlet-mapping>
18        <servlet-name>appServlet</servlet-name>
19        <url-pattern>/</url-pattern>
20    </servlet-mapping>
21</web-app>
A number of things are being done here:
  • We register the DispatcherServlet as as a Servlet called appServlet
  • We map this Servlet to handle incoming requests (relative to the app path) starting with "/"
  • We use the ContextConfigLocation init parameter to customize the location for the base configuration XML file for the Spring Application Context that is loaded by the DispatcherServlet, instead of relying on the default location of<servletname>-context.xml).
Wait, What if Somebody Doesn't Want to Configure Spring via XML?
The default type of Application Context loaded by the DispatcheServlet expects to load at least on XML file with Spring bean definitions. As you'll see, we'll also enable Spring to load Java-based config, alongside the XML.
Everybody will have their own (sometimes very strong) opinion in this area, but while I generally prefer-Java based configuration, I do believe that smaller amounts of XML config for certain areas can sometimes still make more sense, for one of a number of reasons (e.g. ability to change config without recompilation, conciseness of XML namespaces, toolability, etc.). On this basis, this app will use the hybrid approach, supporting both Java and XML.
Rest assured that if you prefer a pure-Java approach, with no Spring XML at all, it's pretty trivial to achieve, by setting one init param in web.xml to override the default Application Context type and use a variant calledAnnotationConfigWebApplicationContext instead.

The Controller

Now let's create a minimal controller:
01package xyz.sample.baremvc;
02 
03import org.springframework.stereotype.Controller;
04import org.springframework.web.bind.annotation.RequestMapping;
05 
06/**
07 * Handles requests for the application home page.
08 */
09@Controller
10public class HomeController {
11 
12    @RequestMapping(value = "/")
13    public String home() {
14        System.out.println("HomeController: Passing through...");
15        return "WEB-INF/views/home.jsp";
16    }
17}
Let's walk through the key aspects of this class:
  • The class has been annotated with the @Controller annotation, indicating that this is a Spring MVC Controller capable of handling web requests. Because @Controller is a specialization of Spring's @Component Stereotype annotation, the class will automatically be detected by the Spring container as part of the container's component scanning process, creating a bean definition and allowing instances to be dependency injected like any other Spring-managed component.
  • The home method has been annotated with a @RequestMapping annotation, specifying that this method should handle web requests to the path "/", i.e. the home path for the application.
  • The home method simply logs a message to system out, and then returns WEB-INF/views/home.jsp, indicating the view which should handle the response, in this case a JSP page. (If hardcoding the entire view path including WEB-INF prefix, and the fact that it's a JSP, seems wrong to you, you are right. We'll deal with this later)
Now, we need to create the view. This JSP page will simply print a greeting.
WEB-INF/views/home.jsp
01<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
02<%@ page session="false" %>
03<html>
04    <head>
05        <title>Home</title>
06    </head>
07    <body>
08        <h1>Hello world!</h1>
09    </body>
10</html>
Finally, as previously mentioned, we need to create a minimal Spring Application Context definition file.
WEB-INF/spring/appServlet/servlet-context.xml
01<?xml version="1.0" encoding="UTF-8"?>
06    xsi:schemaLocation="
10 
11    <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
12 
13    <!-- Scans within the base package of the application for @Components to configure as beans -->
14    <!-- @Controller, @Service, @Configuration, etc. -->
15    <context:component-scan base-package="xyz.sample.baremvc" />
16 
17    <!-- Enables the Spring MVC @Controller programming model -->
18    <mvc:annotation-driven />
19 
20</beans>
Let's examine the contents of this file:
  • You'll note that a few different Spring XML namespaces are being used: context, mvc, and the default beans
  • The <context:component-scan> declaration ensures the Spring container does component scanning, so that any code annotated with @Component subtypes such as @Controller is automatically discovered. You'll note that for efficiency, we limit (to xyz.sample.baremvc in this case) what part of the package space Spring should scan in the classpath
  • The <mvc:annotation-driven> declaration sets up Spring MVC's support for routing requests to @Controllers, as well as how some things like conversion, formatting and validation are handled (with some sensible defaults based on what (libraries) is present in your classpath, and the ability to override if needed)
The web app is now ready to run. Assuming the Servlet container (tc Server in my case) is set to listen on localhost:8080, starting the application and then hitting the URL http://localhost:8080/baremvc via our browser results in a display of the expected greeting:




Enter your email address to get our daily JOBS & INTERVIEW FAQ's Straight to your Inbox.

Make sure to activate your subscription by clicking on the activation link sent to your email