Spring Boot – How Thymeleaf Works?

Thymeleaf is a Java library, 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 at production. Types of templates it can process are – HTML, JAVASCRIPT, CSS, XML, TEXT, RAW.
Template engines used with Spring-Boot:
- Thymeleaf
 - FreeMarker
 - Mustache
 - Groovy
 - Java Server Pages
 
How Thymeleaf works with Spring-Boot?
- Thymeleaf follows a De-Coupled Architecture – It is unaware of any web framework.
 - In the same way, it is unaware of the Spring’s abstraction of model and thus cannot handle the data that the controller places in 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/
Project Structure (Maven)
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> <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> <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;  @Datapublic class OperatingSystem {          public String OS1 ,OS2, OS3;      } | 
Template (index3.html) file:
HTML
<!DOCTYPE html> <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
				
					


