Spring MVC Fast Tutorial: building a Spring MVC web application

How Spring MVC works

Spring MVC works just like most web frameworks (Ruby on Rails, Django, etc):

  • Based on the request URL, a method from a controller class is executed.
  • That controller method often uses a model class to retrieve or store data in a database.
  • A view is rendered and sent as response.

What are we going to build?

A page displaying a list of cars.

We will use our previous project project and add to it:

  • a domain class: Car
  • a model class (also called a service class): will generate a list of cars
  • a controller class: will get the car list from the service class
  • a view (JSP): will display the car list

Create a domain class

Create the Java package com.jeromejaglale.domain and add the class Car to it:

public class Car {
	private String name;
	private BigDecimal price;
 
	// getters and setters
	...
}

Create a service class

Create the Java package com.jeromejaglale.service and add the class CarService to it:

@Service
public class CarService {
	private List<Car> carList = new LinkedList<Car>();
 
	CarService() {
		Car car1 = new Car();
		car1.setName("Mercedes SL");
		car1.setPrice(new BigDecimal(123400));
		carList.add(car1);
 
		Car car2 = new Car();
		car2.setName("BMW M6 Coupé");
		car2.setPrice(new BigDecimal(125000));
		carList.add(car2);
 
		Car car3 = new Car();
		car3.setName("Audi R8");
		car3.setPrice(new BigDecimal(136100));
		carList.add(car3);
	}
 
	public List<Car> findAll() {
		return carList;
	}
}

We hardcoded a list of cars to keep things simple. It would normally be retrieved from a database.

In the AppConfig class, add the service package to @ComponentScan:

...
@ComponentScan(basePackages = {"com.jeromejaglale.service", "com.jeromejaglale.controller"})
public class AppConfig {
...

This will make Spring scan the service package at startup, discover the class CarService and create a CarService object (because of the @Service). We will use that object in our controller class.

Create a controller class

Add the class CarController to the controller package:

@Controller
public class CarController {
	@Autowired
	private CarService carService;
 
	@RequestMapping("/car/list")
	public void carList(Model model) {
		List<Car> carList = carService.findAll();
		model.addAttribute("carList", carList);
	}
}
  • At startup, Spring scans the controller package (because it's declared in @ComponentScan in the AppConfig class) and discovers CarController.
  • Spring knows CarController is a controller because of the class annotation @Controller.
  • The method annotated with @RequestMapping(”/car/list”) will be called by Spring for the route /car/list.
  • The @Autowired field CarService will be initialized by Spring with the instance automatically created at startup.
  • The Model object is used to pass data to the JSP view.
  • Spring will look by default for a view based on the route: /car/list. More in the next section.

Create a JSP view

In the pom.xml file, under <dependencies>, add:

<!-- JSTL -->
<dependency>
	<groupId>javax.servlet</groupId>
	<artifactId>jstl</artifactId>
	<version>1.2</version>
</dependency>

This dependency is required to use the JSP standard tag libray.

In the AppConfig class, add a view resolver for JSPs:

@Bean
public ViewResolver jspViewResolver() {
    InternalResourceViewResolver resolver = new InternalResourceViewResolver();
    resolver.setViewClass(JstlView.class);
    resolver.setPrefix("/WEB-INF/jsp/");
    resolver.setSuffix(".jsp");
    return resolver;
}

At startup, because of @Bean, Spring automatically executes jspViewResolver() and stores the returned ViewResolver, which will be used by Spring when needed. How a view resolver works:

  • a controller returns a String, implicitly or explicitly. In our project, it's implicitly ”/car/list”.
  • a view resolver is automatically used by Spring to find a matching view. This view resolver will look for the file /WEB-INF/jsp/car/list.jsp.

Create the file /WEB-INF/jsp/car/list.jsp:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
<html>
<body>
 
	<h1>Cars</h1>
 
	<c:forEach items="${carList}" var="car">
		<p>
			${car.name}: $${car.price}
		</p>
	</c:forEach>
 
</body>
</html>
  • we use carList, previously initialized in the controller method to display the list of cars.

Test wether it's working

Summary

We've built a complete Spring MVC web application. We have:

  • a service (model) class: CarService
  • a controller class: CarController
  • a view (JSP): /car/list.jsp

The controller gets a list of cars from the service and pass it to the view for display.

The source code is available on GitHub.

Next: Display and process a form
Previous: Hello, World!
Up: Spring MVC Fast Tutorial

Feedback

là il n'y a rien qui fonctionne
reprendre la création de WEB-INF/jsp/car/list.jsp car il en manque pas mal
bernis
Jun 5, 2015
#1
No source code for the JSP view itself?
rw
Jul 4, 2015
#2
It will not work without the class Initializer which implements WebApplicationInitializer

Have you tested? Whether your ServletInitializer is solving this issue?
Saravanan.resume@gmail.com
saravanan
Jul 18, 2015
#3
Added the missing JSP code. If there's any problem, you can look at the source code on GitHub: https://github.com/jeromejaglale/spring4-tutorial
Jerome Jaglale
Sep 4, 2015
#4
where do we have to create the jsp file ??
Sudheer
Dec 10, 2015
#5
Sudheer: in /WEB-INF/jsp/car
Jerome Jaglale
Dec 10, 2015
#6
Sudheer: Create folder named WEB-INF in the src/main/webapp folder, if not already there.
Arun Sharma
May 11, 2016
#7
TNX A LOT
TNX A LOT
Jun 5, 2016
#8
I have this problem:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'authorController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.blazej.service.AuthorsRepository com.blazej.controller.AuthorController.repo; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.blazej.service.AuthorsRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
BS
Jun 16, 2016
#9
my page output looks like not fetching the data. What would be the problem here. need a suggestion.

Cars

${car.name}: $${car.price}
Kannan
Sep 6, 2016
#10
Kannan, try to add this at the beginning of the JSP:

<%@ page isELIgnored="false" %>
Jérôme Jaglale
Sep 7, 2016
#11