片段
片段表达式提供了模板共用的简便方法,同时还可以作为参数传递给其它模板。
最常见的用途是使用 th:insert 或 th:replace 进行片段插入:
<div th:insert="~{commons :: main}">...</div>
同时,它们可以像其他任何变量一样,在任意地方使用:
<div th:with="frag=~{footer :: #main/text()}">
<p th:insert="${frag}">
</div>
关于其详细用法,后续会通过“模板布局”章节,系统地介绍其语法。
字面量
文本字面量
文本常量是指单引号之间指定的字符串。可以包含任何字符,但是需要使用 \' 对单引号进行转义。
<p>
Now you are looking at a <span th:text="'working web application'">template file</span>.
</p>
<p>
Now you are looking at a <span th:text="'working web application, \'thanks very much\'.'">template file</span>.
</p>
数字字面量
数字常量就是日常中的数字。
<p>The year is <span th:text="2013">1492</span>.</p>
<p>In two years, it will be <span th:text="2013 + 2">1494</span>.</p>
布尔字面量
布尔常量即 true 和 false。
<div th:if="${user.isAdmin()} == false"> ...
在次样例中,== false 判断是写在花括号外面的,因此,Thymeleaf引擎将负责处理。如写在花括号里面,则OGNL/SpringEL引擎将负责解析。
<div th:if="${user.isAdmin() == false}"> ...
空字面量
空常量即 null。
<div th:if="${variable.something} == null"> ...
字面量标记
数字、布尔和空字面量实际上是字面量的特殊情况。
这些标记允许在标准表达式中进行一些简化。它们的工作原理与文本字面量('...')完全相同,但是它们仅允许使用字母(A-Z 和 a-z),数字(0-9),方括号([ 和 ]),点(.),连字符(-)和下划线(_)。因此,没有空格,没有逗号等。
要说有点?那就是标记不需要使用任何引号括起来,因此,可以这么做:
<div th:class="content">...</div>
以代替:
<div th:class="'content'">...</div>
文本追加
无论是字面量,还是评估表达式或信息表达式的结果,都可以使用 + 运算符轻松追加文本。
<span th:text="'The name of the user is ' + ${user.name}">
文字替换
文字替换可以轻松格式化包含变量值的字符串,而无需在文字后面附加 '...' + '...'。但这些替换项必须用竖线(|)包围,例如:
<span th:text="|Welcome to our application, ${user.name}!|">
其等价于:
<span th:text="'Welcome to our application, ' + ${user.name} + '!'">
文字替换还可以与其它类型的表达式结合使用:
<span th:text="${onevar} + ' ' + |${twovar}, ${threevar}|">
注意,只有变量/消息表达式(${...},*{...},#{...})允许嵌套在|...| 中。其它如字面量('...'),布尔/数字标记,条件表达式等均不允许。
算数运算
一些算数运算也是可用的,如 +,-, *, / 和 %。
<div th:with="isEven=(${prodStat.count} % 2 == 0)">
请注意,这些运算符也可以在OGNL变量表达式内部应用(在这种情况下,将由OGNL代替Thymeleaf标准表达式引擎解析):
<div th:with="isEven=${prodStat.count % 2 == 0}">
注意,其中一些运算符存在文本别名:div(/),mod(%)。
比较和相等
表达式中的值,可以使用 >,<,>=,<= 符号进行比较,而 == 和 != 则可以用来判断是否相等。注意,xml规范规定,不允许属性值使用 < 和 > 符号,因此应使用 < 和 > 代替。
<div th:if="${prodStat.count} > 1">
<span th:text="'Execution mode is ' + ( (${execMode} == 'dev')? 'Development' : 'Production')">
还有一种更简单的替代方法,就是使用以下这些运算符的文本别名:gt(>),lt(<),ge(>=),le(<=),not(!)。还有 eq(==),neq / ne(!=)。
条件表达式
条件表达式旨在仅根据两个条件的求值结果来求值(其本身就是另一个表达式)。
看一个例子吧:
<tr th:class="${row.even}? 'even' : 'odd'">
...
</tr>
条件表达式的所有三个部分(condition,then 和 else)本身的表达式,这意味着它们可以是变量(${...},*{...}),消息(#{...}),网址(@{...})或文字('...')。
也可以使用括号嵌套条件表达式:
<tr th:class="${row.even}? (${row.first}? 'first' : 'even') : 'odd'">
...
</tr>
Else 表达式也可以省略,在这种情况下,如果条件为 false,则返回 null 值:
<tr th:class="${row.even}? 'alt'">
...
</tr>
默认表达式(Elvis运算符)
默认表达式是一种没有 then 部分的特殊的条件值。它相当于某些预研(如groovy)中的elvis运算符,允许指定两个表达式,如果第一个表达式的计算结果不为null,则使用第一个表达式;如果为null,则使用第二个表达式。
示例:
<div th:object="${session.user}">
...
<p>Age: <span th:text="*{age}?: '(no age specified)'">27</span>.</p>
</div>
如您所见,其运算符为 ?:,并且仅当 *{age} 值结果为null时,才在此处使用它来指定名称的默认值(在这种情况下为文字值)。因此,这等效于:
<p>Age: <span th:text="*{age != null}? *{age} : '(no age specified)'">27</span>.</p>
与条件值一样,它们可以在括号之间包含嵌套表达式:
<p>
Name:
<span th:text="*{firstName}?: (*{admin}? 'Admin' : #{default.username})">Sebastian</span>
</p>
无操作标记
No-Operation标记由下划线符号(_)表示。
该标记旨在标识指定表达式的期望结果是什么也不做,即完全就像可处理属性(例如 th:text)根本不存在一样。
除其它可能性外,这还使开发人员可以将原型文本用作默认值。例如:
<span th:text="${user.name} ?: 'no user authenticated'">...</span>
其替代方案为,将 'no user authenticated' 字符串用作原型文本,从设计角度来说,这使代码既简介又通用。
<span th:text="${user.name} ?: _">no user authenticated</span>
数据转换/格式化
Thymeleaf 为变量表达式(${...})和选择变量表达式(*{...})表达式定义了双括号语法,使我们能够通过配置的转换服务来进行数据转换。如:
<td th:text="${{user.lastAccessDate}}">...</td>
其中,双括号 ${{...}} 的作用即为指示Thymeleaf将 user.lastAccessDate 表达式的结果传递给转换服务,并要求它执行格式操作(将转换为String),然后再写入结果。
假设 user.lastAccessDate 类型为 java.util.Calendar,如果已注册转换服务(IStandardConversionService的实现)并且包含Calendar -> String的有效转换,则将会被应用。
IStandardConversionService的默认实现(StandardConversionService类)只是简单的使用 .toString() 将任何对象转换为String。
官方的thymeleaf-spring3和thymeleaf-spring4集成软件包将Thymeleaf的转换服务机制与Spring自己的转换服务基础结构透明地集成在一起,以便在Spring配置中声明的转换服务和格式化程序将自动提供给 ${{...}} 和 *{{...}} 表达式。
预处理
除了用于表达式处理的所有这些功能之外,Thymeleaf还具有预处理表达式的功能。
预处理是在普通表达式执行之前的执行的表达式,该表达式允许修改最终将要执行的表达式。
预处理表达式与普通表达式完全一样,但是出现了一个双下划线符号(如__${expression}__)。
假设我们有一个i18n Messages_fr.properties条目,其中包含一个OGNL表达式,该表达式调用特定于语言的静态方法,例如:
article.text=@myapp.translator.Translator@translateToFrench({0})
同样的 Messages_es.properties。
article.text=@myapp.translator.Translator@translateToSpanish({0})
我们可以创建一个标记片段,该片段根据语言环境评估一个表达式或另一个表达式。为此,我们将首先选择表达式(通过预处理),然后让Thymeleaf执行它:
<p th:text="${__#{article.text('textVar')}__}">Some text here...</p>
请注意,法语语言环境的预处理步骤将创建以下等效项:
<p th:text="${@myapp.translator.Translator@translateToFrench(textVar)}">Some text here...</p>
预处理字符串 __ 在属性中可以使用 \_\_ 来进行转义。
笔者开通了个人微信公众号【银河架构师】,分享工作、生活过程中的心得体会,填坑指南,技术感悟等内容,会比博客提前更新,欢迎订阅。