为了账号安全,请及时绑定邮箱和手机立即绑定

Thymeleaf模板常用知识点

标签:
Spring

thymeleaf 是新一代的模板引擎,在spring4.0中推荐使用thymeleaf来做前端模版引擎。

thymeleaf介绍

简单说, Thymeleaf 是一个跟 Velocity、FreeMarker 类似的Java模板引擎,它可以完全替代 JSP 。相较与其他的模板引擎,它有如下三个极吸引人的特点:

  • 1.Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。这是由于它遵从web标准,支持 HTML 原型,然后在 html 标签里增加额外的属性来达到模板+数据的展示方式。浏览器解释 html 时会忽略未定义的标签属性,所以 thymeleaf 的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静态内容,使页面动态显示。

  • 2.Thymeleaf 开箱即用的特性,语法优雅易懂。它提供标准和spring标准两种方言,可以直接套用模板实现JSTL、 OGNL表达式效果,避免每天套模板、该jstl、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言。

  • 3.Thymeleaf 提供spring标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。

标准表达式语法

它们分为四类:

  • 1.变量表达式

  • 2.选择或星号表达式

  • 3.文字国际化表达式

  • 4.URL表达式

变量表达式

变量表达式即OGNL表达式或Spring EL表达式(在Spring术语中也叫model attributes)。如下所示:
${session.user.name}
它们将以HTML标签的一个属性来表示:
<span th:text="${book.author.name}">

选择(星号)表达式

选择表达式很像变量表达式,不过它用一个当前选择的对象来代替整个上下文变量映射来执行,如下:
*{customer.name}
被指定的object由th:object属性定义:

<div th:object="${book}">... 
<span th:text="*{title}">...</span> ...</div>

文字国际化(外部化,i8n,消息)表达式

文字国际化表达式允许我们从一个外部文件获取区域文字信息(.properties),用Key索引Value,还可以提供一组参数(可选).

#{main.title} #{message.entrycreated(${entryId})}

可以在模板文件中找到这样的表达式代码:

  <table>  
      ...  
      <th th:text="#{header.address.city}">...</th>  
      <th th:text="#{header.address.country}">...</th>  
      ...  
    </table>
  <table>  
      ...  
      <th th:text="#{header.address.city}">...</th>  
      <th th:text="#{header.address.country}">...</th>  
      ...  
    </table>

URL链接表达式

指的是把一个有用的上下文或回话信息添加到URL,这个过程经常被叫做URL重写。
@{/order/list}
URL还可以设置参数: @{/order/details(id=${orderId})}
绝对路径:  http://www.thymeleaf.org

5bd6f32c0001f66610000469.jpg

链接相对表达式


让我们看这些表达式:


 <form th:action="@{/createOrder}">  
    <a href="main.html" th:href="@{/main}">``` <form th:action="@{/createOrder}">  
    <a href="main.html" th:href="@{/main}">

分段表达式

5bd6f32e000107b210000431.jpg

变量表达式和星号表达有什么区别吗?

如果不考虑上下文的情况下,两者没有区别;星号语法评估在选定对象上表达,而不是整个上下文

什么是选定对象?就是父标签的值,如下:

 <div th:object="${session.user}">
    <p>Name: <span th:text="*{firstName}">Sebastian</span>.</p>
    <p>Surname: <span th:text="*{lastName}">Pepper</span>.</p>
    <p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>
  </div>

这是完全等价于:

 <div th:object="${session.user}">
      <p>Name: <span th:text="${session.user.firstName}">Sebastian</span>.</p>
      <p>Surname: <span th:text="${session.user.lastName}">Pepper</span>.</p>
      <p>Nationality: <span th:text="${session.user.nationality}">Saturn</span>.</p>
  </div>

当然,美元符号和星号语法可以混合使用:

<div th:object="${session.user}">
      <p>Name: <span th:text="*{firstName}">Sebastian</span>.</p>
      <p>Surname: <span th:text="${session.user.lastName}">Pepper</span>.</p>
      <p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>
  </div>

表达式支持的语法

字面(Literals)

  • 文本文字(Text literals):
    <p> Now you are looking at a <span th:text="'working web application'">template file</span>. </p>

  • 数字文本(Number literals):
    <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>

  • 布尔文本(Boolean literals):
    <div th:if="${user.isAdmin()} == false"> ...

  • 空(Null literal):
    <div th:if="${variable.something} == null"> ...

  • 文字标记(Literal tokens):
    <div th:class="content">...</div>

文本操作(Text operations)

  • 字符串连接(String concatenation):+

  • 文本替换(Literal substitutions):|The name is ${name}| #### 算术运算(Arithmetic operations)

  • 二元运算符(Binary operators): +, -, *, /, % * 减号(单目运算符)Minus sign (unary operator):-

布尔操作(Boolean operations)

  • 二元运算符(Binary operators):and, or

  • 布尔否定(一元运算符)Boolean negation (unary operator):!, not

比较和等价(Comparisons and equality)

比较(Comparators): >, <, >=, <= (gt, lt, ge, le)
xml文件禁用<,>
等值运算符(Equality operators):==, != (eq, ne)
<div th:if="${prodStat.count} &gt; 1"> <span th:text="'Execution mode is ' + ( (${execMode} == 'dev')? 'Development' : 'Production')">

条件运算符(Conditional operators)

If-then: (if) ? (then)
If-then-else: (if) ? (then) : (else)
Default: (value) ?: (defaultvalue)
所有这些特征可以被组合并嵌套:
'User is of type ' + (${user.isAdmin()} ? 'Administrator' : (${user.type} ?: 'Unknown'))

常用th标签


5bd6f32f00014ab207600515.jpg



还有非常多的标签,这里只列出最常用的几个,由于一个标签内可以包含多个th:x属性,其生效的优先级顺序为: include,each,if/unless/switch/case,with,attr/attrprepend/attrappend,value/href,src ,etc,text/utext,fragment,remove。


设置属性值

1 Thymeleaf设置任何属性的值

<form action="subscribe.html">
  <fieldset>
    <input type="text" name="email" />
    <input type="submit" value="Subscribe!" />
  </fieldset></form>

和Thymeleaf一样,这个模板更像一个静态的原型,而不是一个Web应用程序的模板。首先,action我们表单中的属性静态链接到模板文件本身,这样就没有有用的URL重写的地方。其次,value提交按钮中的属性使其显示英文文本,但我们希望它是国际化的。

然后输入th:attr属性,以及更改其设置标签的属性值的能力:

<form action="subscribe.html" th:attr="action=@{/subscribe}">
  <fieldset>
    <input type="text" name="email" />
    <input type="submit" value="Subscribe!" th:attr="value=#{subscribe.submit}"/>
  </fieldset></form>

这个概念非常简单:th:attr只需要一个为属性赋值的表达式。创建了相应的控制器和消息文件后,处理这个文件的结果是:

<form action="/gtvg/subscribe">
  <fieldset>
    <input type="text" name="email" />
    <input type="submit" value="¡Suscríbe!"/>
  </fieldset></form>

除了新的属性值之外,还可以看到应用程序上下文名称已经被自动添加到/gtvg/subscribe前面章节中介绍的URL基址的前面。

但是,如果我们想一次设置多个属性呢?XML规则不允许您在标签中设置两次属性,因此th:attr会使用逗号分隔的分配列表,如下所示:

<img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="../../images/gtvglogo.png" 
     th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />

给定所需的消息文件,这将输出:

<img class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="/gtgv/images/gtvglogo.png" title="Logo de Good Thymes" alt="Logo de Good Thymes" />

2 Thymeleaf将值设置为特定的属性

你可能会想这样:
<input type="submit" value="Subscribe!" th:attr="value=#{subscribe.submit}"/>
是一个非常丑陋的标记。在一个属性值中指定一个赋值可能是非常实用的,但是如果你必须一直这样做的话,它不是创建模板的最优雅的方法。

Thymeleaf与你一致,这就是为什么th:attr在模板中很少使用。通常情况下,您将使用其他th:*任务设置特定标签属性的属性(而不仅仅是任何属性th:attr)

例如,要设置value属性,请使用th:value:

<input type="submit" value="Subscribe!" th:value="#{subscribe.submit}"/>

看起来好多了,让我们试着action对form标签中的属性做同样的事情:

<form action="subscribe.html" th:action="@{/subscribe}">

你还记得th:href我们home.html之前放的那些吗?他们正是这种属性:

<li>
    <a href="product/list.html" th:href="@{/product/list}">
      Product List   </a></li>

3 Thymeleaf固定值布尔属性

HTML具有布尔属性的概念,没有值的属性和一个意味着值是“真”的属性

例如checked:

<input type="checkbox" name="option2" checked /> <!-- HTML --><input type="checkbox" name="option1" checked="checked" /> <!-- XHTML -->

标准方言包含的属性允许您通过评估一个条件来设置这些属性,以便如果评估为true,则该属性将被设置为其固定值,如果评估为false,则该属性将不会被设置:

<input type="checkbox" name="active" th:checked="${user.active}" />

Thymeleaf迭代循环

迭代基础

th:each
java.util.List类不是唯一可用于Thymeleaf迭代的值。有一组相当完整的对象被认为可以被迭代
1、任何对象的实现 java.util.Iterable
2、任何对象的实现java.util.Enumeration。
3、任何实现的对象java.util.Iterator,其值将被迭代器返回使用,而不需要缓存内存中的所有值。
4、任何对象的实现java.util.Map。当迭代映射时,iter变量将是类的java.util.Map.Entry。
5、任何数组。
6、任何其他对象将被视为包含对象本身的单值列表。

状态变量

使用时th:each,Thymeleaf提供了一个有用的机制来跟踪迭代状态:状态变量。
状态变量在一个th:each属性中定义并包含以下数据:
. 当前迭代索引,从0开始。这是index属性。
. 当前迭代索引,从1开始。这是count属性。
. 迭代变量中的元素总数。这是size财产。
. 每个迭代的iter变量。这是current财产。
. 目前的迭代是偶数还是奇数。这些是even/odd布尔属性。
. 目前的迭代是否是第一个。这是first布尔属性。
. 目前的迭代是否是最后一个。这是last布尔属性。

<table>
  <tr>
    <th>NAME</th>
    <th>PRICE</th>
    <th>IN STOCK</th>
  </tr>
  <tr th:each="prod,iterStat : ${prods}" th:class="${iterStat.odd}? 'odd'">
    <td th:text="${prod.name}">Onions</td>
    <td th:text="${prod.price}">2.41</td>
    <td th:text="${prod.inStock}? #{true} : #{false}">yes</td>
  </tr></table>

状态变量(iterStat在本例中)是th:each通过在iter变量本身之后写入名称来定义的,用逗号分隔。就像iter变量一样,状态变量的范围也是由持有th:each属性的标签定义的代码片段。

条件语句

有时,如果满足某个条件,则需要模板的一部分才能显示在结果中。

例如,想象一下,我们希望在产品表中显示每个产品存在的评论数量的列,如果有任何评论,则可以链接到该产品的评论详细信息页面。
为了做到这一点,我们将使用th:if属性:

如果值不为空:
. 如果value是一个布尔值并且是true。
. 如果值是一个数字并且是非零的
. 如果值是一个字符,并且是非零的
. 如果value是一个String而不是“false”,“off”或“no”
. 如果值不是布尔值,数字,字符或字符串。
(如果值为null,则th:如果将评估为false)。
此外,th:if还有一个反向属性,th:unless我们可以在前面的示例中使用它,而不是not在OGNL表达式中使用:

还有一种方法可以在Java中使用相当于开关结构的有条件显示内容:th:switch/ th:case属性集。

<div th:switch="${user.role}">
  <p th:case="'admin'">User is an administrator</p>
  <p th:case="#{roles.manager}">User is a manager</p></div>

请注意,只要一个th:case属性被评估为true,th:case同一交换机上下文中的每一个其他属性都被评估为false。

默认选项被指定为th:case="*":

<div th:switch="${user.role}">
  <p th:case="'admin'">User is an administrator</p>
  <p th:case="#{roles.manager}">User is a manager</p>
  <p th:case="*">User is some other thing</p></div>



作者:芥末无疆sss
链接:https://www.jianshu.com/p/1062379d8e1b
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。


点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消