Spring and Thymeleaf 3: Expressions – 春天和百里香3:表达方式

最后修改: 2016年 10月 9日


1. Introduction


Thymeleaf is a Java template engine for processing and creating HTML, XML, JavaScript, CSS and plain text. For an intro to Thymeleaf and Spring, have a look at this write-up.


Besides these basic functions, Thymeleaf offers us a set of utility objects that will help us perform common tasks in our application.


In this article, we’ll discuss a core feature in Thymeleaf 3.0 – Expression Utility Objects in Spring MVC applications. More specifically, we’ll cover the topic of processing dates, calendars, strings, objects and much more.

在这篇文章中,我们将讨论Thymeleaf 3.0的一个核心功能–Spring MVC应用程序中的表达式实用对象。更具体地说,我们将讨论处理日期、日历、字符串、对象等方面的话题。

2. Maven Dependencies


First, let us see the required configuration needed to integrate Thymeleaf with Spring. The thymeleaf-spring library is required in our dependencies:



Note that, for a Spring 4 project, the thymeleaf-spring4 library must be used instead of thymeleaf-spring5. The latest version of the dependencies can be found here.

请注意,对于Spring 4项目,必须使用thymeleaf-spring4库而不是thymeleaf-spring5。最新版本的依赖项可以在这里找到。

3. Expression Utility Objects


Before looking at the core focus of this writeup, if you want to take a step back and see how to configure Thymeleaf 3.0 in your web app project, have a look at this tutorial.

在看这篇报道的核心重点之前,如果你想退一步看看如何在你的Web应用项目中配置Thymeleaf 3.0,可以看看这个教程

For the purpose of the current article, we created a Spring controller and HTML file – to test out all the features we’re going to be discussing. Below is the complete list of available helper objects and their functions:


  • #dates: utility methods for java.util.Date objects
  • #calendars: similar to #dates, used for java.util.Calendar objects
  • #numbers: utility methods for formatting numeric objects
  • #strings: utility methods for String objects
  • #objects: utility methods for Java Object class in general
  • #bools: utility methods for boolean evaluation
  • #arrays: utility methods for arrays
  • #lists: utility methods for lists
  • #sets: utility methods for sets
  • #maps: utility methods for maps
  • #aggregates: utility methods for creating aggregates on arrays or collections
  • #messages: utility methods for obtaining externalized messages inside variables expressions

3.1. Dates Objects

3.1. 日期对象

The first function that we want to discuss is processing of the java.util.Date objects. The expression utility objects responsible for date processing start with #dates.functionName(). The first function that we want to cover is formatting of a Date object (which is added to the Spring model parameters).


Let’s say we want to use ISO8601 format:


<p th:text="${#dates.formatISO(date)}"></p>

No matter how our date was set on the back-end side, it needs to be displayed accordingly to this standard. What’s more, if we want to be specific with the format, we can specify it manually:


<p th:text="${#dates.format(date, 'dd-MM-yyyy HH:mm')}"></p>

The function takes two variables as parameters: Date and its format.


Finally, here are a few similarly useful functions we can use:


<p th:text="${#dates.dayOfWeekName(date)}"></p>
<p th:text="${#dates.createNow()}"></p>
<p th:text="${#dates.createToday()}"></p>

In the first, we will receive the name of the day of the week, in the second we will create a new Date object, and finally we will create a new Date with time set to 00:00.


3.2. Calendar Objects


Calendar utilities are very similar to dates processing, except that we are using an instance of the java.util.Calendar object:


<p th:text="${#calendars.formatISO(calendar)}"></p>
<p th:text="${#calendars.format(calendar, 'dd-MM-yyyy HH:mm')}"></p>
<p th:text="${#calendars.dayOfWeekName(calendar)}"></p>

The only difference is when we want to create new Calendar instance:


<p th:text="${#calendars.createNow().getTime()}"></p>
<p th:text="${#calendars.createToday().getFirstDayOfWeek()}"></p>

Please note, that we may use any Calendar class method in order to get requested data.


3.3. Numbers Processing


Another very handful feature is numbers-processing. Let’s focus on a num variable, randomly created with a double type:


<p th:text="${#numbers.formatDecimal(num,2,3)}"></p>
<p th:text="${#numbers.formatDecimal(num,2,3,'COMMA')}"></p>

In the first line, we format decimal number by setting minimum integer digits and exact decimal digits. In the second one, in addition to integer and decimal digits, we specified the decimal separator. The options are POINT, COMMA, WHITESPACE, NONE or DEFAULT (by locale).


There is one more function that we want to present in this paragraph. It is creation of a sequence of integer numbers:


<p th:each="number: ${#numbers.sequence(0,2)}">
    <span th:text="${number}"></span>
<p th:each="number: ${#numbers.sequence(0,4,2)}">
    <span th:text="${number}"></span>

In the first example, we had Thymeleaf generate a sequence from 0-2, whereas in the second in addition to minimum and maximum value, we provided a definition of step (in this example the values will change by two).


Please note, that the interval is closed on both sides.


3.4. Strings Operations


It is the most comprehensive feature of expression utility objects.


We can start the description with the utility of checking empty or null String objects. Quite often, developers would use Java methods inside Thymeleaf tags to do that, which might be not safe for null objects.

我们可以从检查空或null String对象的效用开始描述。很多时候,开发者会在Thymeleaf标签内使用Java方法来做这件事,这对null对象来说可能不安全。

Instead, we can do this:


<p th:text="${#strings.isEmpty(string)}"></p>
<p th:text="${#strings.isEmpty(nullString)}"></p>
<p th:text="${#strings.defaultString(emptyString,'Empty String')}"></p>

The first String is not empty, so the method will return false. The second String is null, so we will get true. Finally, we may use #strings.defaultString(…) method to specify a default value, if String will be empty.


There are many more methods. All of them works not only with strings but also with Java.Collections. For example to use substring-related operations:


<p th:text="${#strings.indexOf(name,frag)}"></p>
<p th:text="${#strings.substring(name,3,5)}"></p>
<p th:text="${#strings.substringAfter(name,prefix)}"></p>
<p th:text="${#strings.substringBefore(name,suffix)}"></p>
<p th:text="${#strings.replace(name,'las','ler')}"></p>

or to use null-safe comparison and concatenation:


<p th:text="${#strings.equals(first, second)}"></p>
<p th:text="${#strings.equalsIgnoreCase(first, second)}"></p>
<p th:text="${#strings.concat(values...)}"></p>
<p th:text="${#strings.concatReplaceNulls(nullValue, values...)}"></p>

Finally, there are text-style related features, that will preserve the syntax to be always the same:


<p th:text="${#strings.abbreviate(string,5)} "></p>
<p th:text="${#strings.capitalizeWords(string)}"></p>

In the first method, abbreviated text will make it have a maximum size of n. If a text is bigger, it will be clipped and finished with “…”.

在第一种方法中,缩写的文本将使它的最大尺寸为n。如果一个文本更大,它将被剪掉并以”… “结束。

In the second method, we will capitalize words.


3.5. Aggregates


The last but not the least function that we want to discuss here is aggregates. They are null safe, and provide utilities to calculate average or sum from array or any other collection:


<p th:text="${#aggregates.sum(array)}"></p>
<p th:text="${#aggregates.avg(array)}"></p>
<p th:text="${#aggregates.sum(set)}"></p>
<p th:text="${#aggregates.avg(set)}"></p>

4. Conclusion


In this article, we discussed Expression Utility Objects features implemented in the Thymeleaf framework, version 3.0.


The full implementation of this tutorial can be found in the GitHub project.


How to test? Our suggestion is to play with a browser first, then check the existing JUnit tests as well.


Please take a note, that examples do not cover all available utility expressions. If you want to learn about all types of utilities have a look here.