Spring Boot - How Thymeleaf Works?
Last Updated :
23 Jul, 2025
Thymeleaf is a Java library, and template engine used to parse and render the data produced by the application to template files - thus providing transformation. It is just like HTML but is provided with more attributes for working with rendered data. It allows caching of the parsed data/file to increase efficiency while in production. Types of templates it can process are - HTML, JAVASCRIPT, CSS, XML, TEXT, and RAW.
Template engines used with Spring-Boot:
- Thymeleaf
- FreeMarker
- Mustache
- Groovy
- Java Server Pages
How Thymeleaf work with Spring-Boot?
- Thymeleaf follows a De-Coupled Architecture - It is unaware of any web framework.
- In the same way, it is unaware of Spring's abstraction of the model and thus cannot handle the data that the controller places in the Model.
- When Spring-Boot's autoconfiguration detects Thymeleaf in the classpath, it creates beans supporting Thymeleaf view for Spring MVC.
- It can work with request attributes of Servlet.
- Therefore, Spring copies the model data into request attributes that the Thymeleaf template can work with.
Simple life-cycle of Thymeleaf template


To use Thymeleaf, add its dependency in the project build.
Maven - pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
Gradle - build.gradle
compile group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf'
Place the template files in the following directory:
/src/main/resources/templates/

1. Rendering a single model attribute
To render an attribute, use 'th:text' attribute in Thymeleaf Template
<p th:text="${attributeKey}"> attributeValue will be placed here </p>
Controller (TemplateController.java) file:
Java
package gfg;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/")
public class TemplateController {
@GetMapping("/template1")
public String template(Model model) {
String msg = "Welcome to Thymeleaf Template";
// adding the attribute(key-value pair)
model.addAttribute("message", msg);
// returning the view name
return "index";
}
}
Template (index.html) file:
HTML
<!DOCTYPE html>
<html xmlns="https://www.w3.org/1999/xhtml/"
xmlns:th="https://www.thymeleaf.org/">
<head>
<title>GFG</title>
</head>
<body>
<h1>Welcome to GeeksForGeeks...</h1>
<div id="one">
<h1 th:text="${message}">
<span>message will print here</span>
</h1>
</div>
</body>
</html>
Output:

2. Rendering a collection
To render a collection, use 'th:each' attributes in the Thymeleaf template
<p th:each="variable:${collectionName}">
<span th:text=${variable}> items iterated will be placed here </span>
</p>
Note: span tag will be iterated as much as the number of collection items.
Controller (TemplateController2.java) file:
Java
package gfg;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/")
public class TemplateController2 {
@GetMapping("/template2")
public String template(Model model) {
String message = "Top 5 Cloud Service Providers";
// creating a collection
List<String> list = new ArrayList<>();
list.add("Amazon Web Services");
list.add("Microsoft Azure");
list.add("Google Cloud");
list.add("Alibaba Cloud");
list.add("IBM Cloud");
model.addAttribute("message", message);
// adding the collection attribute
model.addAttribute("cloudProvider", list);
return "index2";
}
}
Template (index2.html) file:
HTML
<!DOCTYPE html>
<html xmlns="https://www.w3.org/1999/xhtml/"
xmlns:th="https://www.thymeleaf.org/">
<head>
<title>GFG2</title>
</head>
<body>
<div id="one">
<h2 th:text="${message}">
<span>message will print here</span>
</h2>
</div >
<div id="two" th:each="List:${cloudProvider}">
<ul>
<li>
<span th:text=${List}>items will print here</span>
</li>
</ul>
</div>
</body>
</html>
Output:

3. Binding data to object
Pre-requisites:
- Object to which values will be bound must have 'getter/setter' methods for each field.
- You can use the 'Lombok' library to generate these methods by '@Data' annotation.
Add dependency of Lombok : Maven (pom.xml)
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
Using Thymeleaf, the input data is bound to the object using 'th:object' attribute
<form
method="POST" th:object="${objectName}">
</form>
To map the input to a specific field of object use 'th:field' attribute
<input type="text" th:field="*{fieldName}" />
Controller (TemplateController3.java) file:
Java
package gfg;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import gfg.os.OperatingSystem;
@Controller
@RequestMapping("/template3")
public class TemplateController3 {
@GetMapping
public String template(Model model) {
model.addAttribute("ops", new OperatingSystem());
return "index3";
}
@PostMapping
public String template( @ModelAttribute("ops") OperatingSystem os , Model model) {
model.addAttribute("message", os.getOS1()+" "+os.getOS2()+" "+os.getOS3());
return "index";
}
}
Class of the object to be bound (OperatingSystem.java) file:
Java
package gfg.os;
import lombok.Data;
@Data
public class OperatingSystem {
public String OS1 ,OS2, OS3;
}
Template (index3.html) file:
HTML
<!DOCTYPE html>
<html xmlns="https://www.w3.org/1999/xhtml/"
xmlns:th="https://www.thymeleaf.org/">
<head>
<title>GFG3</title>
</head>
<body>
<h1>Welcome to GeeksForGeeks...</h1>
<form method="POST" th:object="${ops}">
<div><label for="first">First OS</label></div>
<input id="first" type="text" th:field="*{OS1}" />
<div><label for="second">Second OS</label></div>
<input id="second" type="text" th:field="*{OS2}" />
<div><label for="third">Third OS</label></div>
<input id="third" type="text" th:field="*{OS3}" />
<input type="submit" value="Send" />
</form>
</body>
</html>
Output:


Note:
- You can use other attributes of Thymeleaf as well.
- The caching of the template is enabled by default.
- You can turn off caching by specifying the following in the 'application.properties' file.
spring.thymeleaf.cache=false
Explore
Java Basics
OOP & Interfaces
Collections
Exception Handling
Java Advanced
Practice Java