Thymeleaf 是一个跟 FreeMarker、Velocity 类似的模板引擎,是 Spring 所推荐的模板技术 。
Thymeleaf 引以为傲的特性是 自然模板(natural templating) ,即由于主要语法基于标签属性等,使得模板可以直接在静态环境显示正常。
本文内容基于 Thymeleaf3.0 。
本文内容只基于 html模板
,虽然Thymeleaf 提供了文本模板模式(Textual template modes),使其可以作用于 .js
和 .css
,但是这里不会涉及。
方言和属性修改器
方言
Thymeleaf 集成包定义了一种 标准方言 ( SpringStandard Dialect
),其兼容了 Spring EL
,而 Spring EL
基本和 OGNL
相同,所以使用起来十分友好。
属性修改器
标准方言的多数处理器都是属性处理器,Thymeleaf 可以使用两种属性修改器语法 :
属性修改器语法 | 说明 | 示例 |
---|---|---|
th:* |
命名空间语法。 | <input th:value="${username}"> |
data-{prefix}-{name} |
html5自定义属性语法。 | <input data-th-value="${username}"> |
一般来说,使用这种语法是可以直接在浏览器打开的(浏览器会忽略不可识别的属性),所以 Thymeleaf 是 自然模板 。但实际上 th:*
并不符合 HTML5 规范,IDE还是会提示错误。可以使用引入以下 xmlns
命名空间定义:
1 | <html xmlns:th="http://www.thymeleaf.org"> |
可以看出 data-th-*
相较 th:*
对 HTML5 更加友好,两种方式都适用HTML5的各种属性。
但实际上 data-th-*
只是对 th:*
的补充,官方示例推崇 th:*
语法。
其实还有另一种语法:{prefix}:{name}
或 {prefix}-{name}
,其可以指定自定义标签。
例如: 可以使用
th:block
或th-block
元素,来表示自定义标签。
标准表达式语法
在属性修改器中可以使用一些标准表达式是语法。
在大括号外面的数据由Thymeleaf来处理。而在大括号内写的,将由OGNL / SpringEL引擎负责。
涉及一览 | 说明 |
---|---|
${...} |
变量表达式 |
*{...} |
选择变量表达式 |
#{...} |
消息表达式 |
@{...} |
URL 链接表达式 |
变量表达式
通过 ${...}
可以从 context
中获取变量。
使用 .
或者 []
访问属性,相当于调用 getter
。
1 | ${person.father.name} |
对于 Map对象,如下使用,相当于 get(...)
。
1 | ${countriesByCode.ES} |
对于 数组 或 集合 对象,可以使用索引访问。
1 | ${personsArray[0].name} |
甚至可以直接调用方法。
1 | ${person.createCompleteName()} |
实用对象(Expression Utility)
Thymeleaf内置了许多实用对象,这里使用内置工具类格式化日期类型。
1 | <p> |
选择表达式
*{...}
一般配合 th:object
使用,优先从其选定的对象中取值,当没有th:object
时,其作用等同${...}
。
当多次从一个对象中获取属性时,可以如下使用:
1 | <div th:object="${session.user}"> |
其等同于以下写法:
1 | <div> |
消息表达式
使用 #{...}
可以直接使用消息(message),其一般用于国际化。
配置国际化文件 classpath:i18n/messages_zh_CN.properties
。
1 | home.welcome=欢迎来到我们的杂货店! |
在模板中使用消息。
1 | <p th:utext="#{home.welcome}">Welcome to our grocery store!</p> |
URL链接表达式
使用 @{...}
可以用于处理 URL链接。
1 | // 服务器中的上下文名称将自动添加 |
片段表达式
使用 ~{...}
可以将模板片段作为变量使用,这个会在谈Thymeleaf 布局( Layout )时再介绍 。
标准表达式支持的语法
字面(Literals)
其实这里是介绍支持的各种数据类型。
1 | <!-- 文字 --> |
文本操作(Text operations)
转义文本 与 非转义文本
th:text
会转义其中的内容,而 th:utext
则不会转义,这更使用于包含标签
的文本。
1 | home.welcome=Welcome to our <b>fantastic</b> grocery store! |
1 | <p th:text="#{home.welcome}">Welcome to our grocery store!</p> |
1 | <p th:utext="#{home.welcome}">Welcome to our grocery store!</p> |
附加文本(Appending texts)
无论是 文字
还是 评估变量
或 消息表达式的结果
,都可以使用 +
运算符轻松附加:
1 | <span th:text="'The name of the user is ' + ${user.name}"> |
字面替换(Literal substitutions)
当需要将变量值包含到字符串中,可以使用字面替换,而不是用 +
附加文本。
1 | <span th:text="|Welcome to our application, ${user.name}!|"> |
运算
算术运算
一些算术运算也可用: +
, -
, *
, /
, %
。
1 | <div th:with="isEven=(${prodStat.count} % 2 == 0)"> |
比较运算
在标签语言中需要对 <
和 >
进行转义,而 Thymeleaf 还支持别名。
比较运算符 | 别名 |
---|---|
> |
gt |
< |
lt |
>= |
ge |
<= |
le |
! |
not |
== |
eq |
!= |
neq / ne |
1 | <div th:if="${prodStat.count} gt 1"> |
条件运算
属性修改器中也可以使用三目运算符: condition ? then : else
。
else
可以省略,即condition ? then
,若条件为 false ,则返回 null值。
1 | <tr th:class="${row.first}? 'first' : 'even'"> |
默认值(Elvis运算符)
Elvis运算符
类似 条件运算
的变种,可以在取值为 null 时,提供默认值。
1 | <p>Age: <span th:text="{age}?:'(no age specified)'">27</span>.</p> |
无操作令牌
希望原文本为默认值,可以使用 _
代替。
1 | <span th:text="${user.name} ?: _">no user authenticated</span> |
迭代
当需要对集合进行循环遍历是可以使用 th:each
。
不显示设置迭代状态变量,则默认为
迭代变量 + Stat
,即prodStat
。
1 | <table> |
可以显示设置迭代状态变量 iterStat
,如下可以控制奇数行样式。
1 | <table> |
迭代状态变量
状态变量在 th:each
属性中定义,包含以下数据。
迭代变量属性 | 说明 |
---|---|
index |
当前迭代索引,从0开始。 |
count |
当前迭代索引,从1开始。 |
size |
迭代变量中元素的总量。 |
current |
每次迭代的iter变量。 |
even / odd |
当前迭代是否是偶数、奇数,布尔属性。 |
first |
当前迭代是否是第一个迭代。 |
last |
当前迭代是否是最后一次。 |
条件
注意: 条件不仅判断 布尔值,还有如下扩展。
- 如果value不为null,且为以下值则视为
true
,反之视为false
。
- 如果value是布尔值,且为true。
- 如果value是数字且不为零。
- 如果value是一个字符且不为零。
- 如果value是String并且不是“false”,“off”或“no”。
- 如果value不是布尔值,数字,字符或字符串。
- 如果value为null,则th:if将计算为
false
。
th:if
1 | <a href="comments.html" |
th:unless
th:unless
意为除非,与 if
相反, 比使用 not
更加友好。
1 | <a href="comments.html" |
注释
可以看出在注释方面,Thymeleaf 也具有很小的侵入性,完美融入HTML。
涉及一览 | 说明 |
---|---|
<!-- -- > |
hmtl注释 |
<!--/* */-- > |
解析器级注释 |
<!--/*/ /*/-- > |
原型注释 |
标准HTML / XML注释
Thymeleaf 兼容 html注释,其内容不会被解析。
1 | <!-- User info follows --> |
解析器级注释
在解析的,直接删除 <!--/* */-- >
及其中内容。
1 | <!--/* This code will be removed at Thymeleaf parsing time! */--> |
原型注释
在解析完成后,删除 <!--/*/ /*/-- >
,释放其中内容。
1 | <!--/*/ |
元素处理器
Thymeleaf标准方言中包含了唯一的元素处理器(不是属性),即th:block
。
th:block
是一个纯粹的属性容器,允许模板开发人员指定他们想要的任何属性。Thymeleaf将执行这些属性,然后简单地使块,而不使它的内容消失。
因此,在创建 <tr>
每个元素需要多个迭代表时,它可能很有用,且当与仅原型注释块结合使用时尤其有用:
1 | <table> |
内联
在 html模板中,不直接基于标签,而将 Thymeleaf 融入到到 html
,javaScript
, css
中。
涉及一览 | 说明 |
---|---|
[[]] |
转义表达式 |
[()] |
非转义表达式 |
/*[[]]*/ |
自然模板 |
HTML 内联
表达内联
但在某些情况下我们可能更喜欢将表达式直接写入HTML文本,这是可以使用内联表达式 [[]]
或 [()]
。
注意 :虽然看上去会更简洁,但 Thymeleaf表达式 会直接展示在静态环境中,不利于原型设计。
1 | <p>Hello, [[${session.user.name}]]!</p> |
1 | <p>Hello, [(${session.user.name})]!</p> |
禁用内联
可以看出 [[]]
标记会被 Thymeleaf 解析,在某些情况下并不好,这时可以使用 th:inline="none"
禁用此机制。
1 | <p th:inline="none">A double array looks like this: [[1, 2, 3], [4, 5]]!</p> |
JavaScript 内联
JavaScript内联中也支持 [[]]
和 [()]
,但都不能确保取值一定是合适的合法的 js变量
,所以推荐使用 自然模板 ,即 /*[[]]*/
。自然模板也支持默认值,所以对静态环境更加友好。
必须使用
th:inline="javascript"
以下方式明确启用JavaScript 内联模式:
1 | <script th:inline="javascript"> |
CSS 内联
CSS内联中同样支持 [[]]
和 [()]
,但更推荐自然模板 /*[[]]*/
。
必须使用
th:inline="css"
以下方式明确启用css内联模式:
1 | <style th:inline="css"> |