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/
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; @Data public 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