SpringBoot(2): Integrating thymeleaf

Keywords: Thymeleaf Session Fragment Spring

1. Introduction to thymeleaf

Simply put, Thymeleaf is a template engine similar to Velocity and FreeMarker that can complete quan instead of JSP.Compared to other template engines, it has three very attractive features:

  • 1.Thymeleaf works in both networked and networked environments, i.e. it allows artists to view static page effects in a browser or programmers to view dynamic page effects with data on a server.This is because it supports the HTML prototype and then adds additional attributes to the HTML tag to achieve the template + data presentation.Undefined tag properties are ignored when the browser interprets html, so the thymeleaf template can run statically; when data is returned to the page, the Thymeleaf tag dynamically replaces the static content, making the page display dynamically.

  • 2.The out-of-the-box features of Thymeleaf.It provides two dialects, the standard and the spring standard. It can directly tao use templates to achieve JSTL, OGNL expression effect, and avoid the daily tao template, the jstl, and label changes.Developers can also extend and create custom dialects.

  • 3.Thymeleaf provides the spring standard dialect and an optional module that integrates perfectly with spring MVC, enabling fast form binding, property editor, internationalization and other functions.

2. Standard expression syntax

They are divided into four categories:

  • 1). Variable expression
  • 2). Selection or asterisk expression
  • 3). Text Internationalization Expressions
  • 4). URL expression

2.1 Variable expression

Variable expressions are either OGNL or Spring EL expressions (also known as model attributes in Spring terms).As follows:

${session.user.name}

They are represented by an attribute of the HTML tag:

<span th:text="${book.author.name}">  
<li th:each="book : ${books}">  

2.2 Selection (asterisk) expression

Selection expressions are much like variable expressions, but they are executed using a pre-selected object instead of a context variable container (map), as follows:

*{customer.name}

The specified object is defined by the th:object property:

<div th:object="${book}">  
     ...  
     <span th:text="*{title}">...</span>  
     ...  
   </div>  

2.3 Text Internationalization Expressions

Text internationalization expressions allow us to get regional text information (.properties) from an external file, index Value with Key, and provide an optional set of parameters.

  #{main.title}  
  #{message.entrycreated(${entryId})}  

You can find such expression codes in the template file:

<table>  
  ...  
  <th th:text="#{header.address.city}">...</th>  
  <th th:text="#{header.address.country}">...</th>  
  ...  
</table>  

2.4 URL expression

URL expressions refer to the addition of a useful context or callback information to a URL, a process often referred to as URL rewriting.

@{/order/list}

URL s can also set parameters:

@{/order/details(id=${orderId})}

Relative path:

@{../documents/report}

Let's look at these expressions:

<form th:action="@{/createOrder}">  
<a href="main.html" th:href="@{/main}">

What is the difference between a 2.5 variable expression and an asterisk expression?

There is no difference between the two regardless of context; the asterisk syntax evaluates the expression on the selected object, not the entire context What is the selected object?Is the value of the parent label, as follows:

 <div th:object="${session.user}">
    <p>Name: <span th:text="*{firstName}">Sebastian</span>.</p>
    <p>Surname: <span th:text="*{lastName}">Pepper</span>.</p>
    <p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>
  </div>

This is perfect quan equivalent to:

<div th:object="${session.user}">
	  <p>Name: <span th:text="${session.user.firstName}">Sebastian</span>.</p>
	  <p>Surname: <span th:text="${session.user.lastName}">Pepper</span>.</p>
	  <p>Nationality: <span th:text="${session.user.nationality}">Saturn</span>.</p>
</div>

Of course, the dollar sign and asterisk syntax can be mixed:

 <div th:object="${session.user}">
	  <p>Name: <span th:text="*{firstName}">Sebastian</span>.</p>
  	  <p>Surname: <span th:text="${session.user.lastName}">Pepper</span>.</p>
      <p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>
  </div>

Syntax supported by 2.6 expressions

Literals

  • Text literals:'one text','Another one!',...
  • Number literals: 0, 34, 3.0, 12.3,...
  • Boolean literals: true, false
  • Null literal: null
  • Literal tokens: one, sometext, main,...

Text operations

  • String concatenation: +
  • Literal substitutions: |The name is ${name}|

Arithmetic operations

  • Binary operators: +, -, *, /,%
  • Minus sign (unary operator): -

Boolean operations

  • Binary operators: and, or
  • Boolean negation (unary operator):!, not

Comparisons and equality

  • Comparators: >, <, >=, <= (gt, lt, ge, le)
  • Equality operators: ==,!= (eq, ne)

Conditional operators

  • If-then: (if) ? (then)
  • If-then-else: (if) ? (then) : (else)
  • Default: (value) ?: (defaultvalue)

All these features can be combined and embedded in tao:

'User is of type ' + (${user.isAdmin()} ? 'Administrator' : (${user.type} ?: 'Unknown'))

3. What are the common th tags?

4. Centralize commonly used usage methods

1) Assignment, String Stitching

<p  th:text="${collect.description}">description</p>
<span th:text="'Welcome to our application, ' + ${user.name} + '!'">

String splicing has another concise way of writing

<span th:text="|Welcome to our application, ${user.name}!|">

2) Conditional Judgment If/Unless

Thymeleaf uses the th:if and th:unless attributes to make conditional judgments. In the following example, the <a>tag appears only if the condition in th:if is true:

<a th:if="${myself=='yes'}" > </i> </a>
<a th:unless=${session.user != null} th:href="@{/login}" >Login</a>

th:unless, on the contrary, displays the contents of an expression only if the conditions in the expression are not established.

(if)? (then): (else) This grammar can also be used to judge what is displayed.

3) For loop

<tr  th:each="collect,iterStat : ${collects}"> 
     <th scope="row" th:text="${collect.id}">1</th>
     <td >
        <img th:src="${collect.webLogo}"/>
     </td>
     <td th:text="${collect.url}">Mark</td>
     <td th:text="${collect.title}">Otto</td>
     <td th:text="${collect.description}">@mdo</td>
     <td th:text="${terStat.index}">index</td>
 </tr>

iterStat is called a state variable and has the following properties:

Index: The index of the current iteration object (calculated from 0)
count: Index of the current iteration object (calculated from 1)
size:Da xiao of the iterated object
 current:Current iteration variable
 Even/odd: Boolean value, is the current loop even/odd (from 0)?
First: Boolean value, is the current loop the first?
Last: Boolean value, is the current loop the last?

4) URL

URLs play an important role in Web application templates. It is important to note that Thymeleaf handles URLs through the syntax @{...} to process.If you need Thymeleaf to render URLs, be sure to use attributes such as th:href, th:src, and so on. Here is an example

<!-- Will produce 'http://localhost:8080/standard/unread' (plus rewriting) -->
 <a  th:href="@{/standard/{type}(type=${type})}">view</a>

<!-- Will produce '/gtvg/order/3/details' (plus rewriting) -->
<a href="details.html" th:href="@{/order/{orderId}/details(orderId=${o.id})}">view</a>

Set Background

<div th:style="'background:url(' + @{/<path-to-image>} + ');'"></div>

Changing the background based on attribute values

<div class="media-object resource-card-image"  th:style="'background:url(' + @{(${collect.webLogo}=='' ? 'img/favicon.png' : ${collect.webLogo})} + ')'" ></div>

A few notes:

  • The last URL (orderId=${o.id}) in the example above indicates that the contents in parentheses are treated as URL parameters. This syntax avoids string splicing and greatly improves readability
  • The @{...} expression can access the orderId variable in the Context through {orderId}
  • @{/order} is the relative path related to the Context, which automatically adds the Context name of the current Web application when rendered. Assuming the Context name is app, the result should be / app/order

5) Inline js

Inline text: [[...]] Inline text representation, when used, must first be activated with th:inline="text/javascript/none", th:inline can be used within parent tags, or even as a body tag.Inline text, though fewer than th:text, is not good for prototyping.

<script th:inline="javascript">
/*<![CDATA[*/
...
var username = /*[[${sesion.user.name}]]*/ 'Sebastian';
var size = /*[[${size}]]*/ 0;
...
/*]]>*/
</script>

js additional code:

/*[+
var msg = 'This is a working application';
+]*/

js Remove Code:

/*[- */
var msg = 'This is a non-working template';
/* -]*/

6. Embedded Variables

To make the template easier to use, Thymeleaf also provides a series of Utility objects (built into the Context) that can be accessed directly from #:

  • dates: Functional method class for java.util.Date.
  • calendars: like #dates, for java.util.Calendar
  • Number: Functional method class for formatting numbers
  • strings: Functional class of string object, contains,startWiths,prepending/appending, etc.
  • Objects: Functional class operations on objects.
  • bools: Functional method for evaluating Boolean values.
  • Arrays: Functional class method for arrays.
  • Lists: Functional class methods for lists
  • sets
  • maps ...

Here is a code to illustrate some common methods: dates

/*
 * Format date with the specified pattern
 * Also works with arrays, lists or sets
 */
${#dates.format(date, 'dd/MMM/yyyy HH:mm')}
${#dates.arrayFormat(datesArray, 'dd/MMM/yyyy HH:mm')}
${#dates.listFormat(datesList, 'dd/MMM/yyyy HH:mm')}
${#dates.setFormat(datesSet, 'dd/MMM/yyyy HH:mm')}

/*
 * Create a date (java.util.Date) object for the current date and time
 */
${#dates.createNow()}

/*
 * Create a date (java.util.Date) object for the current date (time set to 00:00)
 */
${#dates.createToday()}

strings

/*
 * Check whether a String is empty (or null). Performs a trim() operation before check
 * Also works with arrays, lists or sets
 */
${#strings.isEmpty(name)}
${#strings.arrayIsEmpty(nameArr)}
${#strings.listIsEmpty(nameList)}
${#strings.setIsEmpty(nameSet)}

/*
 * Check whether a String starts or ends with a fragment
 * Also works with arrays, lists or sets
 */
${#strings.startsWith(name,'Don')}                  // also array*, list* and set*
${#strings.endsWith(name,endingFragment)}           // also array*, list* and set*

/*
 * Compute length
 * Also works with arrays, lists or sets
 */
${#strings.length(str)}

/*
 * Null-safe comparison and concatenation
 */
${#strings.equals(str)}
${#strings.equalsIgnoreCase(str)}
${#strings.concat(str)}
${#strings.concatReplaceNulls(str)}

/*
 * Random
 */
${#strings.randomAlphanumeric(count)}

6) Using the thymeleaf layout

Very convenient to use thymeleaf layout

Define snippets

<footer th:fragment="copy"> 
&copy; 2016
</footer>

Introduce anywhere on the page:

<body> 
  <div th:include="footer :: copy"></div>
  <div th:replace="footer :: copy"></div>
 </body>

th:include differs from th:replace in that includ is only load and replace is replacement

The HTML returned is as follows:

<body> 
   <div> &copy; 2016 </div> 
  <footer>&copy; 2016 </footer> 
</body>

Below is a common background page layout that divides the whole page into header, tail, menu bar, hidden bar, click menu to change only the pages in the content area

<body class="layout-fixed">
  <div th:fragment="navbar"  class="wrapper"  role="navigation">
	<div th:replace="fragments/header :: header">Header</div>
	<div th:replace="fragments/left :: left">left</div>
	<div th:replace="fragments/sidebar :: sidebar">sidebar</div>
	<div layout:fragment="content" id="content" ></div>
	<div th:replace="fragments/footer :: footer">footer</div>
  </div>
</body>

Any page that wants to use this layout value simply needs to replace the content module seen in the

<html xmlns:th="http://www.thymeleaf.org" layout:decorator="layout">
  <body>
     <section layout:fragment="content">
   ...

You can also pass it around when referencing a template

<head th:include="layout :: htmlhead" th:with="title='Hello'"></head>

Layout is the file address, if there is a folder you can write fileName/layout:htmlhead htmlhead is a defined snippet such as th:fragment="copy"

Source case: Sample Code-github

Posted by nsr500rossi on Wed, 15 May 2019 18:58:37 -0700