Spring MVC is the Spring framework's traditional library for building Java web applications. It is one of the most popular web frameworks for building fully functional Java web applications and RESTful web services. In this tutorial, you'll get an overview of Spring MVC and learn how to build Java web applications using Spring Boot, Spring Initializr, and Thymeleaf.
Spring Boot with Spring Initializr
We'll fastrack our Spring MVC web application with the help of Spring Boot and Spring Initializr. Given input for the type of application to be built, Spring Initializr uses the most common dependencies and defaults to setup and configure a basic Spring Boot application. You can also add custom dependencies and Spring Initializr will include and manage them, ensuring version compatibility with both third-party software and Spring. Spring Boot applications run standalone, without requiring you to provide a runtime environment.
In this case, since we're building a web application, Spring Boot will automatically include and configure Tomcat as part of the app's runtime. We can also customize the app by adding an H2 database driver to our Maven POM file. Spring Boot will then automatically create an embedded database and DataSource
instance in the application context. Once the dependencies are set, Spring Boot will provide default configurations for the application. Of course we can change the configurations if we want to, but thanks to Spring Boot we have a headstart: a fully configured, working application right out of the box.
Once we've selected and configured our dependencies, we'll pass those selections to Spring Initializr, which will provide a downloadable ZIP file containing a base Spring Boot project.
Spring MVC with H2 database engine
We'll start by creating a basic Spring MVC web application that persists data to an H2 embedded database.
Step 1. Setup and configure the app
Navigate to Spring Initializr at start.spring.io and select Generate a Maven Project with Java and Spring Boot 2.0.X, where X is the latest Spring Boot version (2.0.3 at time of this writing). Make sure you select Spring Boot 2.x so that you can implement Spring Web MVC 5. Spring Boot 1.4 and Spring Boot 1.5 will implement Spring 4.
Enter a group name with the format matching your web address, such as com.geekcap.javaworld
, and enter an artifact name, such as spring5mvc-example
. Figure 1 shows my configuration.
Figure 1. Config for Spring Initializr
To add dependencies to the web app, you may either enter a comma-separated list of dependencies into the Search for dependencies text field or click on Switch to the full version. We'll take the easier route by clicking on Switch to the full version. The dependencies are divided into groups, such as Core, Web, and Template Engines. For this example, select the checkboxes for: Web-->Web, Template Engines-->Thymeleaf, SQL-->JPA, and SQL-->H2. Here's what each of those selections will add to the application:
- Web: Spring MVC and Tomcat
- Thymeleaf: Thymeleaf web template engine
- JPA: Spring JPA, Hibernate, and Spring Data
- H2: The H2 embedded database
When you're finished, click the Generate Project button at the bottom of the page. Spring Initializr will create a readymade ZIP file with all the required project sources, which you can download.
Step 2. Import the Spring Initializr project to your IDE
Extract the ZIP file from Spring Initializr, then import the project into your favorite IDE. For example, to import the project into IntelliJ, choose File-->New Project, as shown in Figure 2.
Figure 2. Importing the project into IntelliJ
Step 3. Setup your Maven POM
Next, navigate to Import project from external module, choose Maven, and press Next. Be sure to choose a Java 1.8 project SDK, then hit Finish.
The Spring Boot starter app
Now let's take a look at the Spring Boot starter application that has been generated by our (minimal) efforts so far.
To start, Listing 1 shows the Maven POM file.
Listing 1. Maven pom.xml
<?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.geekcap.javaworld</groupId>
<artifactId>spring5mvc-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>spring5mvc-example</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Notice that the POM file uses a special parent POM: spring-boot-starter-parent
. We'll use the parent POM to manage the versions of all our dependencies and ensure versions are compatible. The repositories at the end of the POM file reference the Spring snapshot and milestone repositories. We need these because Spring Boot 2.x is still a milestone release at the time of this writing.
The dependencies are quite minimal, and most are prefaced with spring-boot-starter
:
spring-boot-starter-data-jpa
spring-boot-starter-thymeleaf
spring-boot-starter-web
spring-boot-starter-test
Each of these starter dependencies brings in all of the sub-dependencies it needs. Figure 3 shows the partially expanded dependency view in IntelliJ.
Figure 3. Spring starter project dependencies
The POM file includes the following dependencies:
spring-boot-starter-data-jpa
includes Hibernate and Spring Data.spring-boot-starter-thymeleaf
includes the Thymeleaf template engine.spring-boot-starter-web
includesspring-boot-starter-tomcat
, an embedded version of Apache Tomcat.spring-boot-starter-json
includes the Jackson JSON libraries.spring-web and spring-webmvc
includes Spring MVC.spring-boot-starter-test
includes testing libraries such as JUnit and Mockito.
When Spring Boot sees these dependencies in the CLASSPATH, it initiates automatic configuration. For example, when it finds spring-boot-starter-web
, it creates an embedded version of Tomcat, and when it finds H2 and spring-boot-starter-jpa
it creates an H2 embedded database and a Hibernate EntityManager
. It then wires the EntityManager
into Spring Data.
Spring Boot also creates a single class that can be used to run the application. The class for the example application is shown in Listing 2.
Listing 2. Spring5mvcExampleApplication.java
package com.geekcap.javaworld.spring5mvcexample;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Spring5mvcExampleApplication {
public static void main(String[] args) {
SpringApplication.run(Spring5mvcExampleApplication.class, args);
}
}
This class leverages the SpringApplication.run()
method, passing in the class to run (Spring5mvcExampleApplication
in this example). The @SpringBootApplication
annotation includes the following annotations:
@Configuration
informs Spring that theSpring5mvcExampleApplication
class contains configuration information. (This annotation can be used to create beans that will get registered with the Spring context.)@EnableAutoConfiguration
tells Spring to automatically configure resources from dependencies found in the CLASSPATH, such as H2 and Tomcat.@ComponentScan
tells Spring to scan packages in the CLASSPATH under the current package (com.geekcap.javaworld.spring5mvcexample
) for Spring-annotated components such as@Service
and@Controller
.
Spring scans the CLASSPATH and automatically creates components such as the embedded Tomcat server and H2 database. It then populates the Spring context with the application components found in the package scan. In essence, Spring Boot makes it very easy to select and configure the services, components, controllers, entities, and so forth that you need for your application. Once you've done that, Spring will automatically find them, make them available in the Spring context, and autowire everything together.
We've got our Spring Boot starter project setup and ready to go. In the next section we'll create the Spring MVC components for our Java web application.
About Spring MVC 5
Spring MVC implements the popular Model-View-Controller pattern, which you've probably seen in other web frameworks. The Model-View-Controller pattern separates concerns into three categories:
- Model represents your domain objects.
- View renders your model to a view, such as to an HTML page.
- Controller sits between your view and model and translates change requests in the view into changes in the model, and vice versa. In practical terms, the controller accepts incoming requests, potentially updates the model, and sends your model objects to a "view" to render back to the client.
In Spring MVC, controllers are identified by the @Controller
annotation and accompanied by a @RequestMapping
annotation. The annotation defines the HTTP verb (standard HTTP commands like GET, POST, PUT, and DELETE) and URI for which the request-mapping method will be applied. Spring 4 introduced shortcut request mappings, which make things even easier. We'll use these mappings--@GetMapping
, @PostMapping
, @PutMapping
, @PatchMapping
, and @DeleteMapping
--for our example application.
The model in Spring MVC
For our application, we'll define a simple model object, a Widget
, store it in an embedded H2 database, and build a controller to manage widgets. Let's start with the Widget
class, which is shown in Listing 3.