Spring Boot – How Thymeleaf Works?

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?

  1. Thymeleaf follows a De-Coupled Architecture – It is unaware of any web framework.
  2. 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.
  3. When Spring-Boot’s autoconfiguration detects Thymeleaf in the classpath, it creates beans supporting Thymeleaf view for Spring MVC.
  4. It can work with request attributes of Servlet.
  5. 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="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org">
 <head>
 <title>GFG</title>
 </head>
 <body>
 <h1>Welcome to w3wiki...</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="http://www.w3.org/1999/xhtml"
 xmlns:th="http://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="http://www.w3.org/1999/xhtml"
 xmlns:th="http://www.thymeleaf.org">
 <head>
 <title>GFG3</title>
 </head>
 <body>
 <h1>Welcome to w3wiki...</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



Contact Us