Spring's MVC is a request based framework like Struts but it clearly separates the presentation, request handling and model layers.
In this post, I'll describe how to get the most simple of examples up and running using Maven, therefore providing a basis upon which to add more features of Spring MVC like handler mappings, complex controllers, commons validator etc..
Let's start with the
pom.xml file. This will package up the project as a war file and only requires three dependencies namely the artifacts
spring-webmvc, servlet-api and jstl. The
spring-webmvc artifact will pull in all the other required spring jars like core, web, etc.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.city81</groupId>
<artifactId>spring-mvc</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1-beta-1</version>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.0.5.RELEASE</version>
<optional>false</optional>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
</project>
Note that the scope of the
servlet-api is provided and therefore excluded from the war file. If deployed as part of the war, there'll be conflict with the servlet jar of the container, and there'll be an error similar to the one below when deploying to Tomcat:
INFO: Deploying web application archive spring-mvc-0.0.1-SNAPSHOT.war
15-Nov-2011 16:05:27 org.apache.catalina.loader.WebappClassLoader validateJarFile
INFO: validateJarFile(C:\apache-tomcat-6.0.33\webapps\spring-mvc-0.0.1-SNAPSHOT\WEB-INF\lib\servlet-api-2.5.jar) - jar not loaded. See Servlet Spec 2.3, section
9.7.2. Offending class: javax/servlet/Servlet.class
Next the
web.xml located in the
/webapp/WEB-INF folder:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>Spring MVC Example</display-name>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>springMVCExample</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMVCExample</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>home.jsp</welcome-file>
</welcome-file-list>
</web-app>
The context loader is a listener class called
ContextLoaderListener. By default this will load the config in the /
WEB-INF/applicationContext.xml but you can specify more files by adding a
contextConfigLocation param and list one or more xml files. For example,
contextConfigLocation /WEB-INF/example-persistence.xml
/WEB-INF/example-security.xml
If an
applicationContext.xml file isn't present when not using a context param list, then the WAR won't deploy properly. An example empty
applicationContext.xml is below:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
</beans>
The servlet's configuration does not need to be explicitly specified as it can be loaded by following the same naming convention of the servlet, in this case
springMVCExample-servlet.xml. The servlet is the front controller which delegates requests to other parts of the system.
The
servlet-mapping tags in the
web.xml denote what URLs the
DispatcherServlet will handle. In this example HTML.
Also included in the
web.xml by way of the
welcome-file, is a default home page. This doesn't have to be included but the page can be used to forward a request as can be seen later in the post.
As mentioned previously, the servlet's config is in it's own XML file. This describes the mapping between the a URL and the
Controller which will handle the request. It also contains the a
ViewResolver which maps the view name in the
ModelAndView to an actual view. The
springMVCExample-servlet.xml is shown below:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean name="/example.htm" class="com.city81.spring.mvc.ExampleController">
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/jsp/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
</beans>
The
ExampleController class is shown below. It extends
AbstractController therefore must implement the method
handleRequestInternal(HttpServletRequest request, HttpServletResponse response). The return value of this method is a
ModelAndView object. This object is constructed by passing in the view name (example), the model name (message) and the model object (in this case a String)
package com.city81.spring.mvc;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractController;
public class ExampleController extends AbstractController {
protected ModelAndView handleRequestInternal(
HttpServletRequest request, HttpServletResponse response)
throws Exception {
ModelAndView modelAndView = new ModelAndView("example", "message", "Spring MVC Example");
return modelAndView;
}
}
The view jsp will then have the
${message} value populated by the model object from the
ModelAndView. The
example.jsp is below and resides in the
/webapp/WEB-INF/jsp folder:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Spring MVC Example</title>
</head>
<body>
<h2>Welcome to the Example Spring MVC page</h2>
<h3>The message text is:</h3>
<p>${message}</p>
</body>
</html>
As mentioned previously, a default home page can included in the
web.xml and instead of displaying html etc., it can be used to redirect requests to another URL. The below
home.jsp redirects requests to
example.htm:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:redirect url="/example.htm"/>
Deploying the above to a container like Tomcat should result in a page like the following:
This is just the very basics of Spring MVC but later posts, will expand on the framework and show how it can be used with, for example, web services like REST.