This tutorial describes how to create a simple Spring MVC web application statring from a basic Maven project. We set up the required directories and files by hand, almost nothing will be pre-generated.
Tools I used for this tutorial:
- Spring Tool Suite (STS) 3.4.0.RELEASE (you can also use Eclipse)
- Maven 3.0.5
Creating the Maven project
- In STS press Ctrl + N, this brings up the New wizard where you select what kind of project or file you would like to create. In the search box enter maven. From the filtered list select Maven Project.
- Click Next.
- Check the Create a simple project (skip archetype selection) checkbox.
- Click Next.
- Set the following properties:
- Group Id: com.jtuts
- Artifact Id: spring-mvc-maven-webapp-from-scratch
- Packaging: war
- Name: spring-mvc-maven-webapp-from-scratch
- Click Finish.
Of course the Group Id, Artifact Id and Name properties can be set to anything else, these are just example values. However the war value for the Packaging is mandatory, because we are creating a web application and the server which will run it (in our case Tomcat) expects a .war file.
The directory structure
STS will automatically create the basic directory structure for our application. This conforms to the basic structure that Maven expects. You can find more information about it on Maven’s Introduction to the Standard Directory Layout page.
The most important directories for us are:
- src/main/java: Java source files.
- src/main/resources: Other resources like property files and xml files.
- src/main/webapp: Web application source files (e.g. JPSs, images, CSS files).
- src/test/java: Test source files.
- src/test/resources: Resources for tests.
By default, Maven expects you to have the above mentioned files in these directories. You can change this in Maven’s pom.xml but you should avoid it not to create confusion when other developers look at your project.
The pom.xml
The pom.xml file is added automatically by STS when you create the Maven project. However, we made some additions that are needed for our webapp to work. This is what the final pom.xml looks like:
<?xml version="1.0" encoding="UTF-8"?> <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.jtuts</groupId> <artifactId>spring-mvc-maven-webapp-from-scratch</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <name>spring-mvc-maven-webapp-from-scratch</name> <properties> <spring.version>4.1.0.RELEASE</spring.version> <servlet.api.version>3.0.1</servlet.api.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>${servlet.api.version}</version> <scope>provided</scope> </dependency> </dependencies> <build> <finalName>spring-mvc-maven-webapp-from-scratch</finalName> <plugins> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <path>/${project.build.finalName}</path> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.1</version> <configuration> <source>1.7</source> <target>1.7</target> </configuration> </plugin> </plugins> </build> </project>
In this file we include all the dependencies that are required by our example project. We also have a tag which configures the build process of Maven.
The finalName will be the name of the .war file that is created.
Then, we have two plugins:
- The tomcat7-maven-plugin can be used to enable Maven to start an embedded Tomcat server and run our app inside it. It also specifies that the context path under which our app will be available (in this case we use the value of the finalName): /spring-mvc-maven-webapp-from-scratch.
- With the maven-compiler-plugin we configure the compilation process of Maven. In this case we set that our source code must be compatible with at least Java 1.7, and we want our compiled program to be executable with Java 1.7 and above.
Creating the web.xml file
The web.xml file must be placed in the /src/main/webapp/WEB-INF/ folder is the Web Application Deployment Descriptor of your application. So you have to create the WEB-INF directory in the /src/main/webapp/ directory and inside it create a file named web.xml. This file is an XML document that defines everything about your application that a server needs to know: servlets and other components like filters or listeners, initialization parameters, container-managed security constraints, resources, welcome pages, etc.
The full path for this file is: /src/main/webapp/WEB-INF/web.xml
In this project we will use the following web.xml file:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" 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_3_0.xsd"> <display-name>Spring MVC application from scratch</display-name> <servlet> <servlet-name>mvc-dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/dispatcher-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>mvc-dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:spring/application-context.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
The <web-app> element
This is the root element of you web.xml file.
The attributes inside the <web-app>
tag mean that the file uses the 3.0 version of the Servlet Specification.
Defining the DispatcherServlet
The job of the DispatcherServlet is to take an incoming URI and find the right combination of handlers (generally methods on Controller classes) and views (generally JSPs) that combine to form the page or resource that’s supposed to be found at that location.
<servlet> <servlet-name>mvc-dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/dispatcher-servlet.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
Let’s see the definition of the servlet step by step.
<servlet-name>mvc-dispatcher</servlet-name>
Defines the name by which we can reference the servlet.
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
The class that contains the servlet’s code.
<init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/dispatcher-servlet.xml</param-value> </init-param>
The contextConfigLocation
parameter tells the DispatcherServlet
which xml to use for setting up the WebApplicationContext. This will be a child to the root WebApplicationContext defined by ContextLoaderListener
and can access every bean in it.
<load-on-startup>1</load-on-startup>
For load-on-startup
a value of >=0 means that the servlet is loaded when the web-app is deployed or when the server starts. A value < 0 means that the servlet is loaded whenever the container feels like. Also, the container must guarantee that servlets marked with lower integers are loaded before servlets marked with higher integers. The container may choose the order of loading of servlets with the same load-on-startup value.
The ContextLoaderListener
<context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:spring/application-context.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
The ContextLoaderListener creates the root WebApplicationContext for your application. This application context contains all the beans defined in the xml specified as the value of the contextConfigLocation
parameter. Also, the beans from this context are available in any child contexts (such as the one we created with the DispatcherServlet
).
The dispatcher-servlet.xml file
Create a file named dispatcher-servlet.xml in the src/main/resources/spring directory. It could be anywhere else, but it is good practice to group spring context xml files in a common directory.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" 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-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd"> <context:component-scan base-package="com.jtuts.spring.mvc.webapp.controller" /> <mvc:annotation-driven /> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix"> <value>/WEB-INF/views/</value> </property> <property name="suffix"> <value>.jsp</value> </property> </bean> </beans>
This first line tells spring to go over the classes in the com.jtuts.spring.mvc.webapp.controller
package and register them as spring beans if they have the appropriate annotation. In our case we have only one such class which is a controller and this is signified by putting a @Controller
annotation on the class.
The <mvc:annotation-driven>
tag enables a couple of spring features like mapping requests to controllers, validating form data with the @Valid
annotation, using the ConversionService and so on.
The viewResolver
bean will handle the resolving of our views (in this case jsp files). The prefix
property’s value will be prepended to the name of every view we request and the suffix
property’s value will be appended to the requested view name. So, for example if we request the view “home” then the viewResolver will modify this to /WEB-INF/views/home.jsp. This bean enables Spring to find our views, and also lets us write shorter view names because we can omit the common parts from path.
The application-context.xml file
Create file named application-context.xml in the src/main/resources/spring directory. It should contain the following:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" 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-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd"> </beans>
For this basic application this file does not define or configure anything, but when extending our application with additional functionality we can define the beans for our root application context here in the same manner we did in the dispatcher-servlet.xml. So this file currently is just an empty placeholder for future bean definitions and configuration.
The controller
We need a controller to provide a response when the user requests a specific URL. Create a class called HomeController
in the com.jtuts.spring.mvc.webapp.controller
package, and put the following code in it:
package com.jtuts.spring.mvc.webapp.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.ModelAndView; @Controller public class HomeController { @RequestMapping("home") public ModelAndView home2() { return new ModelAndView("home"); } }
In Spring MVC each controller is a class ann otated with the @Controller
annotation. These classes handle incoming requests. A controller can handle multiple requests with multiple methods. The @RequestMapping
annotation means that in case of which request urls should spring invoke this method. The method returns a ModelAndView object which contains the view we would like to display and also the model (the data to be displayed in the view). In this case we use the
public ModelAndView(String viewName)
constructor of the ModelAndView
class which expects the name of the view to be displayed. Additional model parameters are not retured in this simple example.
The view (jsp) file
We also need a simple jsp file in the project which we will show to the user if they request /home. In this example the full URL, where this page is available is: http://localhost:8080/spring-mvc-maven-webapp-from-scratch/home
Create a views directory in the WEB-INF folder, and inside it create a home.jsp file with the following content:
<%@ page language="java" contentType="text/html; charset=UTF-8" %> <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Spring MVC web application from scratch</title> </head> <body> <h1>Welcome to the home page.</h1> </body> </html>
The concrete file will be found by the viewResolver
bean we defined earlier. It uses the prefix, the view name we returned from the controller, and the suffix. These concatenated will form the correct path to the home.jsp file.
Starting the web application
In the command line navigate to the root directory of the application and execute the command mvn clean install tomcat7:run
. This compiles the project, packages into a .war file, starts an embedded tomcat server and deploys the war file in it.
After the process is completed we can access the app at http://localhost:8080/spring-mvc-maven-webapp-from-scratch/home
Download
You can download the complete source files for this project here.