thymeleaf(5) - 标准表达式语法

官方文档:https://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html#standard-expression-syntax

参考博客:http://www.ityouknow.com/springboot/2016/05/01/spring-boot-thymeleaf.html

 

首先,我们看一下标准表达式功能的快速摘要。

(1)简单表达式

  • 变量表达式:${...}
  • 选择变量表达式:*{...}
  • 国际化(消息)表达式:#{...}
  • URL表达式:@{...}

(2)字面(Literals)

  • 文本:'one text' 'another one'
  • 数字:0 34 3.0
  • 布尔(Boolean):true false
  • 空:null
  • 文字标记:one sometext main...

(3)文本操作

  • 字符串连接:+
  • 文字替换:|名称是${userName}|

(4)算术运算

  • 二元运算:+ - * / %
  • 减号(一元运算符):-

(5)布尔操作

  • 二元运算:and or
  • 布尔否定(一元运算符):!  not

(6)比较和等价

  • 比较:>  <  >=  <= (gt  lt  ge  le)
  • 等值运算符:==  != (eq  ne)

条件运算符

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

所有这些功能可以组合和嵌套使用:

'用户角色是:' + (${user.isAdmin()} ? '管理员' : (${user.type} ?: '未知角色'))

 

1. 国际化

我们已经知道#{...}消息表达式允许我们链接:

<p th:utext="#{home.welcome}">欢迎来到商店!</p>

在home_en.properties配置了该key

home.welcome=¡Bienvenido a nuestra tienda de comestibles!

这样的写法适用于纯静态,但是用户已经登录了,我们如何动态的取出用户姓名?

取出这个名字需要我们添加一个参数到我们的message上

home.welcome=¡Bienvenido a nuestra tienda de comestibles, {0}!

参数根据java.text.MessageFormat标准表达式指定,这也意味着你可以给数字或日期添加指定的格式。

为了给参数一个具体的值,在session中添加user,写法如下:

<p th:utext="#{home.welcome(${session.user.name})}">
  Welcome to our grocery store, Sebastian Pepper!
</p>

假如必要的话,可以定义多个参数,以英文逗号分隔。实际上,key本身可以来自变量:

<p th:utext="#{${welcomeMsgKey}(${session.user.name})}">
  Welcome to our grocery store, Sebastian Pepper!
</p>

2. 变量

${...}表达式实际是在上下文中包含的map执行OGNL(Object-Graph Navigation Language:对象图导航语言)表达式。OGNL详细用法参考:http://commons.apache.org/ognl/

getter方法导航是OGNL的用法之一,更多用法如下:

/*
 * 使用.访问属性,等价于调用getter方法
 */
${person.father.name}

/*
 * 也可以通过[]访问属性,属性名称在单引号间作为一个变量
 */
${person['father']['name']}

/*
 * 假如对象是map,使用 . 或 []语法都等价于调用get(...)方法
 */
${countriesByCode.ES}
${personsByName['LM'].age}

/*
 * 使用下标方式访问数组或集合
 */
${personsArray[0].name}

/*
 * 通过参数执行方法
 */
${person.createCompleteName()}
${person.createCompleteNameWithSeparator('-')}

2.1 表达式基本对象

在上下文变量上使用OGNL表达式时,一些对象可以用于表达式从而获得更高的灵活性。 使用#号将引用这些对象(按照OGNL标准),主要有以下几个对象,其他对象及使用方法参考官方文档附录A:

  • #ctx:上下文对象
  • #vars:上下文变量
  • #local:上下文locale
  • #httpServletRequest:(web上下文)HttpServletRequest对象
  • #httpSession:(web上下文)HttpSession对象

示例:

当前国家: <span th:text="${#locale.country}">中国</span>.

2.2 表达式工具对象

除了上面的基本对象,Thymeleaf还提供了一系列工具对象帮助我们在表达式处理一些常见任务,所有这些对象的方法参考官方文档的附录B:https://www.thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html#appendix-b-expression-utility-objects

主要有下面这些工具对象:

  • #dates: java.util.Date 对象实用方法: 格式转换等
  • #calendars: 类似于#dates, 但是java.util.Calendar对象
  • #numbers: 格式化数字实用方法
  • #strings: 字符串实用方法: contains, startsWith, prepending/appending等
  • #objects: 对象实用方法
  • #bools: boolean实用方法
  • #arrays: 数组实用方法
  • #lists: list列表实用方法
  • #sets: set集合实用方法
  • #maps: map集合实用方法
  • #aggregates: 数组或集合上创建聚合的实用方法
  • #messages: 在变量表达式中获取外部化消息的实用方法,与使用#{...}语法获得的方法相同
  • #ids: 处理可能重复的id属性的实用方法(例如,作为迭代的结果)

2.3 示例 - 格式化日期

<p>
  今天是: <span th:text="${#calendars.format(today,'yyyy-MM-dd HH:mm:ss')}">2018-08-10 07:45:00</span>
</p>

3. 选择表达式(星号表达式)

变量表达式不仅可以用${...}表达式,还可以使用*{...}表达式。

星号表达式在选定的对象中执行而不是整个上下文map变量。但是只要没有选定对象,${...}和*{...}没有区别。

示例:

<div th:object="${session.user}">
    <p>姓名: <span th:text="*{name}">小明</span>.</p>
    <p>性别: <span th:text="*{sex}">男</span>.</p>
    <p>年龄: <span th:text="*{age}">18</span>.</p>
</div>

 等价于:

<div>
  <p>姓名: <span th:text="${session.user.name}">小明</span>.</p>
  <p>性别: <span th:text="${session.user.sex}">男</span>.</p>
  <p>年龄: <span th:text="${session.user.age}">18</span>.</p>
</div>

 ${...}和*{...}可以混合使用:

<div th:object="${session.user}">
  <p>姓名: <span th:text="${#object.name}">小明</span></p>
  <p>性别: <span th:text="${session.user.sex}">男</span></p>
  <p>年龄: <span th:text="*{age}">18</span></p>
</div>

没有选定对象,${...}和*{...}等价

<div>
  <p>姓名: <span th:text="*{session.user.name}">小明</span>.</p>
  <p>性别: <span th:text="*{session.user.sex}">男</span>.</p>
  <p>年龄: <span th:text="*{session.user.age}">18</span>.</p>
</div>

 

4. URL表达式

由于它们的重要性,URL是Web应用程序模板中的'一等公民',Thymeleaf标准方言有一个特殊的语法,@ 语法:@ {...}

不同类型的URL:

  • 绝对路径:例如http://www.thymeleaf.org
  • 相对路径:
    • 相对于当前页面:user/login.html
    • 相对于上下文:/itemdetails?id=3,服务器中应用上下文名称(项目名称)会被自动添加,
    • 相对于服务器:~/billing/processInvoice,允许在同一服务器链接到另外的上下文
    • 相对于协议://code.jquery.com/jquery-2.0.3.min.js

Thymeleaf可以在任何情况下处理绝对URL,但对于相对URL,它要求使用实现IWebContext接口的上下文对象,该接口包含来自HTTP请求的一些信息以及创建相对链接所需的信息。

示例:

<!-- 结果:'http://localhost:8080/projName/order/details?orderId=3' -->
<a href="details.html" 
   th:href="@{http://localhost:8080/gtvg/order/details(orderId=${o.id})}">查看</a>

<!-- 结果:'/projName/order/details?orderId=3' -->
<a href="details.html" th:href="@{/order/details(orderId=${o.id})}">查看</a>

<!-- 结果:'/projName/order/3/details' -->
<a href="details.html" th:href="@{/order/{orderId}/details(orderId=${o.id})}">查看</a>

提示:

  • th:href是一个属性修饰符属性:一旦处理,它将会计算使用的URL,并将<a>标签的href属性设置为该值。
  • 允许URL参数上使用表达式(例如:orderId=${o.id}),自动执行URL编码操作
  • 假如需要设置多个参数,使用逗号分隔,例如:@{/order/process(id=${id},type='fast')}
  • URL路径中允许使用变量模板,例如:@{/order/{orderId}/details(orderId=${orderId})}
  • 以 / 开头的相对URL(如:/order/details),自动会添加应用上下文名称(项目名称)
  • 假如未启用cookie或不知道cookie,一个';jsessionid=...'可以被添加为相对路径的后缀,确保session会话保留。这被称作URL重写,Thymeleaf允许通过Servlet API为每个URL使用response.encodeURL(...)机制来插入自己的重写过滤器。
  • th:href标签允许我们(可选的)在我们的模板中有一个静态的href属性,便于我们在设计静态页面时浏览器仍然可以打开链接。

与消息语法(#{...})一样,URL也可以是表达式的结果:

<a th:href="@{${url}(orderId=${o.id})}">查看</a>
<a th:href="@{'/details/'+${user.login}(orderId=${o.id})}">查看</a>

4.1 主页菜单

我们知道了如何创建url,在我们主页添加一个小菜单用于打开其他页面:

<p>请选择</p>
<ol>
  <li><a href="product/list.html" th:href="@{/product/list}">产品列表</a></li>
  <li><a href="order/list.html" th:href="@{/order/list}">订单列表</a></li>
  <li><a href="subscribe.html" th:href="@{/subscribe}">意见反馈</a></li>
  <li><a href="userprofile.html" th:href="@{/userprofile}">用户信息</a></li>
</ol>

 4.2 相对于服务器根目录的URL

可以另外一个语法来创建相对于服务器根目录的(不是相对于上下文)URL,以便链接到同一服务器中的不同上下文。 这些URL将被定义为:@ {〜/path/ o/something}

 

5. 字面量

5.1 文本字面量

文本字符就是字符串,定义在单引号间。这之间可以包含任意字符,假如是单引号则需要使用转移:\'

<p>
  文本字面量:<span th:text="'web应用'"></span>.
</p>

5.2 数字字面量

数字字面量也就是数字

<p>今年是<span th:text="2018">2018</span>.</p>
<p>两年后将会是<span th:text="2018 + 2">2020</span>.</p>

5.3 Boolean字面量

包括true和false,例如

<div th:if="${user.isAdmin()} == false"> ...

提示:在上面的例子中,==false写在大括号之外,Thymeleaf本身负责处理它;如果实在大括号中,它将由OGNL/SpringEL负责处理。

<div th:if="${user.isAdmin() == false}"> ...

5.4 null字面量

null字面量也可以向上面例子一样使用:

<div th:if="${variable.something} == null"> ...

5.5 文本标记

数字、boolean、null字面量是文本标记的特例。

这些文本标记允许在标准表达式中进行一些简化。 它们与文本文字('...')完全相同,但只允许字母(A-Z和a-z),数字(0-9),括号([ ]),点(.),连字符( - ) 和下划线(_)。 所以没有空格、逗号等。

好处?文本标记不需要任何的单引号括起来。所以我们可以这样做:

<div th:class="content">...</div>
<!-- 上面的写法替代下面的 -->
<div th:class="'content'">...</div>

 

6. 文本拼接

文本,不管是字面量或变量表达式执行结果或消息表达式,都可以使用 + 操作:

th:text="'姓名:' + ${user.name}"

 

7. 文字替换

文字替换可以轻松地格式化包含变量值的字符串,不需要使用+操作。这些替换需要用| |括起来,例如:

<span th:text="|欢迎, ${user.name}!|">

上面的写法等价于:

<span th:text="'欢迎, ' + ${user.name} + '!'">

文字替换可以结合其他类型的表达式:

<span th:text="${onevar} + ' ' + |${twovar}, ${threevar}|">

提示:只有变量表达式${...}允许写在| |里面,('...')、boolean、数字标记和条件表达式不允许。

 

8. 算术运算

支持一些算术运算:+ - / * %

th:with="isEven=(${prodStat.count} % 2 == 0)"

这些运算也可以写在OGNL表达式内,这种情况下由OGNL负责执行,而不是Thymeleaf标准表达式yin引擎:

th:with="isEven=${prodStat.count % 2 == 0}"

提示:其中一些运算符存在文本别名:div(/)、mod(%)

 

9. 比较和相等

在表达式中,值可以通过> < >= <=进行比较,还可以通过== !=运算符比较相等或不等。提示:XML的< >符号不能再属性中使用,使用它们应该替换为&lt; $gt;

th:if="${prodStat.count} &gt; 1"
th:text="'执行模式是:' + ( (${execMode} == 'dev')? '开发环境' : '生产环境')"

提示:其中一些运算符存在文本别名:gt(>)  lt(<)  ge(>=)  lw(<=)  not(!)  eq(==)  neq/ne(!=)

 

10. 条件表达式

条件表达式用于判断两个表达式中的一个,取决于判断的结果。示例:(th:class :class属性修饰符)

<tr th:class="${row.even}? 'even' : 'odd'">
  ...
</tr>

条件表达式的三个部分(condition then 和 else),它们本身也是表达式,这就意味着它们可以是变量${....},*{...},消息#{...},URL(@{...})或者字面量('...')

条件表达式可以使用括号嵌套:

<tr th:class="${row.even}? (${row.first}? 'first' : 'even') : 'odd'">
  ...
</tr>

Else表达式可以省略,这种情况下,如果条件为false,返回null

<tr th:class="${row.even}? 'alt'">
  ...
</tr>

 

11. 默认表达式(Elvis运算符)

默认表达式是一种特殊条件值,它没有then部分。它等价于一些语言中的Elvis 运算符,例如Groovy,允许指定两个表达式,第二个表达式在第一个表达式返回null时计算。

示例:

<div th:object="${session.user}">
  ...
  <p>年龄: <span th:text="*{age}?: '(未获取到年龄)'">18</span>.</p>
</div>

如上面例子所示,运算符?:,当*{age}是null时,我们可以使用它指定一个默认值。等价于下面的写法:

<p>年龄: <span th:text="*{age != null}? *{age} : '(未获取到年龄)'">18</span>.</p>

与条件表达式一样,可以通过括号嵌套表达式:

<p>
  姓名: 
  <span th:text="*{name}?: (*{admin}? '管理员' : #{default.name})">小明</span>
</p>

 

12. 预处理

除了用于处理表达式的功能外,Thymeleaf还为我们提供了预处理表达式。

预处理可以做什么? 它在正常表达式之前完成表达式的执行,它允许修改最终实际执行的表达式。

预处理表达式与普通表达式完全相同,使用双下划线包围,如:  __ $ {expression} __

假设我们有一个i18n Messages_fr.properties配置文件,其中包含一个OGNL表达式,调用特定语言的静态方法,如:

article.text=@myapp.translator.Translator@translateToFrench({0})

es(西班牙) Messages_es.properties配置文件如下:

article.text=@myapp.translator.Translator@translateToSpanish({0})

我们可以创建一个标记片段,根据语言环境判断一个表达式或另一个表达式。 为此,我们将首先选择表达式(通过预处理),然后让Thymeleaf执行它:

<p th:text="${__#{article.text('textVar')}__}">其他内容...</p>

提示:法语区域设置的预处理步骤将创建以下等效项:

<p th:text="${@myapp.translator.Translator@translateToFrench(textVar)}">其他内容...</p>

 如果在属性中要使用预处理字符串'__',可以使用'\_\_'进行转义。

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值