5分钟内开始使用标准方言
本指南将带您了解理解使用Thymeleaf模板编写的标准方言所需知道的一些最重要的概念。标准或SpringStandard这不能替代教程——教程要全面得多——但它会教会你足够的内容,让你感受到这项技术的感觉。
标准方言?
Thymeleaf 非常、非常可扩展,它允许您使用您想要的名称定义自己的模板属性集(甚至是标签),以您想要的语法评估您想要的表达式,并应用您想要的逻辑。它更像是一个模板引擎框架.
然而,默认情况下,它自带一种叫做标准方言(命名为标准和SpringStandard)这些方言定义了一组功能,应该足以应对大多数场景。您可以通过模板中包含以th
前缀开头的属性来识别何时在模板中使用了这些标准方言,例如:<span th:text="...">
.
请注意,标准和SpringStandard方言几乎完全相同,区别在于SpringStandard包含特定于集成到 Spring MVC 应用程序的功能(比如,例如使用Spring 表达式语言来进行表达式评估而不是OGNL)。
同时请注意,当我们谈论Thymeleaf而不进一步明确时,通常指的是标准方言中的特性。
标准表达式语法
大多数Thymeleaf属性允许其值被设置为或包含表达式,我们将称之为标准表达式因为其所使用的方言。它们可以是五种类型:
${...}
: 变量表达式。*{...}
: 选择表达式。#{...}
: 消息 (i18n) 表达式。@{...}
: 链接 (URL) 表达式。~{...}
: 片段表达式。
变量表达式
变量表达式是OGNL表达式——或者如果您将Thymeleaf与Spring集成,则是Spring EL表达式——在上下文变量上执行的——也称为模型属性在Spring术语中。它们看起来像这样:
${session.user.name}
您会在属性值或部分属性值中找到它们,具体取决于属性:
<span th:text="${book.author.name}">
上面的表达式等同于(无论是在OGNL还是SpringEL中):
((Book)context.getVariable("book")).getAuthor().getName()
但我们可以在不仅涉及输出的场景中找到变量表达式,还包括更复杂的处理,如条件判断, 迭代…
<li th:each="book : ${books}">
这里${books}
选择上下文中名为books
的变量,并将其作为可迭代对象使用于th:each
循环中。
选择表达式
选择表达式和变量表达式一样,只是它们将在之前选定的对象上执行,而不是整个上下文变量映射表。它们看起来像这样:
*{customer.name}
它们操作的对象由th:object
属性指定:
<div th:object="${book}">
...
<span th:text="*{title}">...</span>
...
</div>
所以这相当于:
{
// th:object="${book}"
final Book selection = (Book) context.getVariable("book");
// th:text="*{title}"
output(selection.getTitle());
}
消息 (i18n) 表达式
消息表达式(常常被称为文本外化, 国际化或i18n)允许我们从外部来源(.properties
文件)通过键来检索特定区域的消息,并且(可选地)应用一组参数。
在Spring应用程序中,这将自动与Spring的MessageSource
机制集成。
#{main.title}
#{message.entrycreated(${entryId})}
您可以在模板中找到它们,如下所示:
<table>
...
<th th:text="#{header.address.city}">...</th>
<th th:text="#{header.address.country}">...</th>
...
</table>
请注意,如果您希望消息键由上下文变量的值决定,或者希望指定变量作为参数,可以在变量表达式中使用消息表达式:
#{${config.adminWelcomeKey}(${session.user.name})}
链接 (URL) 表达式
链接表达式的目的是构建URL并为它们添加有用的内容和会话信息(这个过程通常称为URL重写)。
应用上下文中的Web应用程序,这样的表达式:/myapp
对于部署在Web服务器的
<a th:href="@{/order/list}">...</a>
可以转换为类似这样的内容:
<a href="/myapp/order/list">...</a>
或者甚至这样,如果我们需要保持会话并且cookies未启用(或者服务器尚未知晓)的情况:
<a href="/myapp/order/list;jsessionid=23fa31abd41ea093">...</a>
URL也可以带有参数:
<a th:href="@{/order/details(id=${orderId},type=${orderType})}">...</a>
结果可能类似这样:
<!-- Note ampersands (&) should be HTML-escaped in tag attributes... -->
<a href="/myapp/order/details?id=23&type=online">...</a>
链接表达式也可以是相对路径的,在这种情况下,URL前面不会加上应用上下文:
<a th:href="@{../documents/report}">...</a>
同样,服务器相对路径的(同样不需要加上应用上下文):
<a th:href="@{~/contents/main}">...</a>
以及协议相对路径的(类似于绝对URL,但浏览器将使用当前页面显示所使用的相同HTTP或HTTPS协议):
<a th:href="@{//static.mycompany.com/res/initial}">...</a>
当然,链接表达式也可以是绝对路径的:
<a th:href="@{http://www.mycompany.com/main}">...</a>
但等等,在绝对(或协议相对)URL中……Thymeleaf链接表达式有什么价值?很简单:由响应过滤器定义的可能性进行URL重写::在基于Servlet的Web应用程序中,对于每一个输出的URL(相对于应用上下文的、相对的、绝对的……),Thymeleaf总是会在显示URL之前调用HttpServletResponse.encodeUrl(...)
方法。这意味着过滤器可以通过包装HttpServletResponse
对象(一个常用的机制)来自定义应用程序的URL重写。
片段表达式
片段表达式是一种简单的方法,用于表示标记片段并在模板之间移动它们。有了这些表达式,片段可以复制、作为参数传递给其他模板等等。
最常见的用途是使用th:insert
或th:replace
:
<div th:insert="~{commons :: main}">...</div>
插入片段。
<div th:with="frag=~{footer :: #main/text()}">
<p th:insert="${frag}">
</div>
片段表达式可以有参数:
提供了许多字面量类型和操作:
提供了许多字面量类型和操作:
- 字面量:
- 文本字面量:
'one text'
,'Another one!'
,… - 数字字面量:
0
,34
,3.0
,12.3
,… - 布尔字面量:
true
,false
- 空字面量:
null
- 字面令牌:
one
,sometext
,main
,…
- 文本字面量:
- 文本操作:
- 字符串连接:
+
- 文字替换:
|The name is ${name}|
- 字符串连接:
- 算术运算:
- 二元运算符:
+
,-
,*
,/
,%
- 减号(一元运算符):
-
- 二元运算符:
- 布尔运算:
- 二元运算符:
and
,or
- 布尔取反(一元运算符):
!
,not
- 二元运算符:
- 比较和相等性:
- 比较运算符:
>
,<
,>=
,<=
(gt
,lt
,ge
,le
) - 相等性运算符:
==
,!=
(eq
,ne
)
- 比较运算符:
- 条件运算符:
- 如果-那么:
(if) ? (then)
- 如果-那么-否则:
(if) ? (then) : (else)
- 默认值:
(value) ?: (defaultvalue)
- 如果-那么:
表达式预处理
关于表达式,最后需要了解的是有一种称为表达式预处理的机制,使用__
包裹,看起来像这样:
#{selection.__${sel.code}__}
我们在上面看到的是一个变量表达式(${sel.code}
),它将首先执行,并且其结果——比如说“ALL
”——将作为后续实际执行的表达式的一部分使用,在此例中是一个国际化表达式(将会查找键为selection.ALL
)。
一些基本属性
让我们来看看标准方言中最基础的一些属性。从th:text
开始,它只是替换标签体内容(再次注意这里的原型功能):
<p th:text="#{msg.welcome}">Welcome everyone!</p>
Now th:each
,该属性会根据其表达式返回的数组或列表的数量重复所在元素多次,并创建一个用于迭代元素的内部变量,语法类似于Java的foreach表达式:
<li th:each="book : ${books}" th:text="${book.title}">En las Orillas del Sar</li>
最后,Thymeleaf包含了许多th
针对特定XHTML和HTML5属性的属性,它们仅评估其表达式并将其结果设置为这些属性的值。它们的名称模仿了它们所设置值的属性名称:
<form th:action="@{/createOrder}">
<input type="button" th:value="#{form.submit}" />
<a th:href="@{/admin/users}">
想要了解更多吗?
那么你应该看看“使用Thymeleaf”教程!