Thymeleaf标准方言

本节将带您了解一些最重要的概念,以了解以标准或SpringStandard方言编写的Thymeleaf模板。

1. 什么是标准方言?

Thymeleaf是非常非常可扩展的,它允许自定义的名字来定义一组模板属性(或者甚至是标签),用自定语法评估计算表达式和应用逻辑。它更像是一个模板引擎框架。

它还带有一些称为标准方言(称为StandardSpringStandard)的东西,它们定义了一组功能,这些功能应该足以满足大多数情况。可以识别这些标准方言在模板中的使用,因为它将包含以th前缀开头的属性,如<span th:text="...">

请注意,StandardSpringStandard方言几乎完全相同,只是SpringStandard包含了集成到Spring MVC应用程序中的特定功能(例如,使用Spring表达式语言进行表达式评估而不是OGNL)。

2. 标准表达式语法

大多数Thymeleaf属性允许将它们的值设置为或包含表达式,由于它们使用的方言,我们将其称为标准表达式。这些表达式可以有五种类型:

  • ${...} : 变量表达式。
  • *{...} : 选择表达式。
  • #{...} : 消息 (i18n) 表达式。
  • @{...} : 链接 (URL) 表达式。
  • ~{...} : 片段表达式。

2.1 变量表达式

变量表达式是OGNL表达式 - 如果将ThymeleafSpring - 集成在上下文变量上(也称为Spring术语中的模型属性),则为Spring EL。 它们看起来像这样:

${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中使用循环将其评估为迭代器。

2.2 选择表达式

选择表达式就像变量表达式一样,它们不是整个上下文变量映射上执行,而是在先前选择的对象。 它们看起来像这样:

*{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());
}

2.3 消息(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})}

2.4 链接(URL)表达式

链接表达式在构建URL并向其添加有用的上下文和会话信息(通常称为URL重写的过程)。
因此,对于部署在Web服务器的/myapp上下文中的Web应用程序,可以使用以下表达式:

<a th:href="@{/order/list}">...</a>

可以转换成如下的东西:

<a href="/myapp/order/list">...</a>

甚至,如果需要保持会话,并且cookie未启用(或者服务器还不知道),那么生成的格式为:

<a href="/myapp/order/list;jsessionid=s2ds3fa31abd241e2a01932">...</a>

网址也可以带参数,如下所示:

<a th:href="@{/order/details(id=${orderId},type=${orderType})}">...</a>

这将产生类似以下的结果 -

<!-- 注意&符号会在标签属性中进行HTML转义... -->
<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(上下文相对,相对,绝对…),在显示URL之前,Thymeleaf总是调用HttpServletResponse.encodeUrl(...)机制。 这意味着一个过滤器可以通过包装HttpServletResponse对象来为应用程序执行自定义的URL重写。

2.5 片段表达式

片段表达式是一种简单的方法用来表示标记的片段并将其移动到模板中。 由于这些表达式,片段可以被复制,传递给其他模板的参数等等。

最常见的是使用th:insertth:replace来插入片段:

<div th:insert="~{commons :: main}">...</div>

但是它们可以在任何地方使用,就像任何其他变量一样:

<div th:with="frag=~{footer :: #main/text()}">
  <p th:insert="${frag}">
</div>

片段表达式可以有参数。

2.6 文字和操作

有很多类型的文字和操作可用,它们分别如下:

  • 文字

    • 文本文字,例如:'one text', 'Another one!',
    • 数字文字,例如:0,10, 314, 31.01, 112.83,
    • 布尔文字,例如:true,false
    • Null文字,例如:Null
    • 文字标记,例如:one, sometext, main,
  • 文本操作:

    • 字符串连接:+
    • 文字替换:|The name is ${name}|
  • 算术运算:

    • 二进制操作:+, -, *, /, %
    • 减号(一元运算符):-
  • 布尔运算:

    • 二进制运算符,and,or
    • 布尔否定(一元运算符):!,not
  • 比较和相等:

    • 比较运算符:>,<,>=,<=(gt,lt,ge,le)
    • 相等运算符:==, != (eq, ne)
  • 条件操作符:

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

2.7 表达式预处理

关于表达式的最后一件事是知道表达式预处理,在__之间指定,如下所示:

#{selection.__${sel.code}__}

上面代码中,第一个被执行的变量表达式是:${sel.code},并且将使用它的结果作为表达式的一部分(假设${sel.code}的结果为:ALL),在此处执行国际化的情况下(这将查找与关键selection.ALL消息)。

3. 基本的属性

下面来看看标准方言中的几个最基本的属性。 从th:文本开始,它代替了标签的主体:

<p th:text="#{msg.welcome}">Welcome everyone!</p>

现在,th:each重复它所在元素的次数,由它的表达式返回的数组或列表所指定的次数,为迭代元素创建一个内部变量,其语法与Java的foreach表达式相同:

<li th:each="book : ${books}" th:text="${book.title}">En las Orillas del Sar</li>

最后,Thymeleaf为特定的XHTML和HTML5属性提供了许多th属性,这些属性只评估它们的表达式,并将这些属性的值设置为结果。

<form th:action="@{/createOrder}">
<input type="button" th:value="#{form.submit}" />
<a th:href="@{/admin/users}">