Spring Boot 3 MVC: A Step-by-Step Tutorial

In this tutorial we will learn how to create an application based on the Spring MVC pattern, and the Template engine Thymeleaf to render the page View.

This tutorial will guide you through building a simple Spring Boot 3 MVC application. The application will manage customer records with the ability to add, update, list, and delete customers. The frontend will use Thymeleaf templates for rendering the views.

Prerequisites

Setting Up the Spring Boot MVC Project

Start by creating a new Spring Boot project using Spring Initializr or your IDE. Include the following dependencies:

The Model

The Customer class represents the customer entity. It is annotated with @Entity to map it to the database table.

import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.Id; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Entity @Data @NoArgsConstructor @AllArgsConstructor public class Customer

The Repository

The repository interface extends JpaRepository to provide CRUD operations on the Customer entity.

import org.springframework.data.jpa.repository.JpaRepository; public interface CustomerRepository extends JpaRepository

The Service

The service layer encapsulates business logic. It uses the repository to interact with the database:

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; import java.util.Optional; @Service public class CustomerServiceImpl implements ICustomerService < @Autowired private CustomerRepository repo; @Override public Customer save(Customer customer) < return repo.save(customer); >@Override public List findAll() < return repo.findAll(); >@Override public Customer getCustomerById(Long id) < Optionalopt = repo.findById(id); if (opt.isPresent()) < return opt.get(); >else < throw new CustomerNotFoundException("Customer with Id : " + id + " Not Found"); >> @Override public void deleteCustomerById(Long id) < repo.delete(getCustomerById(id)); >@Override public void update(Customer customer) < repo.save(customer); >>

The Controller

The controller handles HTTP requests, interacts with the service layer, and returns the appropriate views.

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.*; import java.util.List; @Controller @RequestMapping("/customer") public class CustomerController < @Autowired private ICustomerService service; @GetMapping("/") public String showHomePage() < return "homePage"; >@GetMapping("/register") public String showRegistration() < return "registerCustomerPage"; >@PostMapping("/save") public String saveCustomer(@ModelAttribute Customer customer, Model model) < Long String message = "Record with id : '" + id + "' is saved successfully!"; model.addAttribute("message", message); return "registerCustomerPage"; >@GetMapping("/getAllCustomers") public String getAllCustomers(@RequestParam(value = "message", required = false) String message, Model model) < Listcustomers = service.findAll(); model.addAttribute("list", customers); model.addAttribute("message", message); return "allCustomersPage"; > @GetMapping("/edit") public String getEditPage(Model model, RedirectAttributes attributes, @RequestParam Long id) < try < Customer customer = service.getCustomerById(id); model.addAttribute("customer", customer); return "editCustomerPage"; >catch (CustomerNotFoundException e) < attributes.addAttribute("message", e.getMessage()); return "redirect:getAllCustomers"; >> @PostMapping("/update") public String updateCustomer(@ModelAttribute Customer customer, RedirectAttributes attributes) < service.update(customer); attributes.addAttribute("message", "Customer with id: '" + customer.getId() + "' is updated successfully!"); return "redirect:getAllCustomers"; >@GetMapping("/delete") public String deleteCustomer(@RequestParam Long id, RedirectAttributes attributes) < try < service.deleteCustomerById(id); attributes.addAttribute("message", "Customer with Id : '" + id + "' is removed successfully!"); >catch (CustomerNotFoundException e) < attributes.addAttribute("message", e.getMessage()); >return "redirect:getAllCustomers"; > >

The Views

Within the src/main/resources/templates we will be adding the views for our Spring MVC application. We will add the following HTML pages:

├── resources/ │ ├── static/ │ │ │ └── css/ │ │ ├── templates/ │ │ │ ├── allCustomersPage.html │ │ │ ├── editCustomerPage.html │ │ │ ├── homePage.html │ │ │ └── registerCustomerPage.html │ │ └── application.properties

The Home page

The homePage.html is the landing page of our application. When we request the Root Context for the application (“/”) the Controller will redirect to this page:

     

Spring Boot MVC Example

Add Customer " btn-primary">Show All Customers

Here is how to page will look when you request the customer endpoint ( http://localhost:8080/customer ):

Spring boot 3 MVC tutorial

The Add Customer View

By Clicking on the “Add Customer” button, the navigation will continue in the registerCustomerPage.html View which contains a Form to insert a new Customer:

      .label-column  

Add Customer




" btn-primary">Show All Customers

Here is our Add Customer View in Action:

<a href=spring boot mvc getting started" width="671" height="419" />

The List Customer View

To list the Customers in a tabular style we can use the following View ( allCustomersPage.html ) which will loop through the Customer. Within it, the th:each loop is a Thymeleaf attribute used to iterate over a collection of objects and display them in the HTML template. In this specific context, it’s used to iterate over a list of Customer objects and render each one as a row in an HTML table.

      

Customer List

ID Name Surname Email Edit/Delete > > > > )>" btn-danger">DELETE | )>" btn-warning">EDIT " btn-success ">Add Customer " btn-primary">Go to Home

Here is the Customer List View in Action:

<a href=spring boot mvc example" width="663" height="403" />

The Edit Customer View

For the sake of completeness, we will also include the editCustomer.html page which allows editing an existing Customer:

      

Edit Customer

ID

NAME

SURNAME

EMAIL

" btn-primary">Show All Customers
We are done. You can build the application and access it at http://localhost:8080/customer/

Conclusion

This tutorial covered the basics of building a Spring Boot 3 MVC application with Thymeleaf for the view layer. You learned how to:

You can extend this project by adding more features like validation, error handling, and integrating with a persistent database like MySQL or PostgreSQL.

Found the article helpful? if so please follow us on Socials