Thymeleaf标准表达式语法
两种简单语法:<p th:utext="#{home.welcome}">Welcome to our grocery store!</p>
<p>Today is: <span th:text="${today}">13 february 2011</span></p>
-
简单表示式:
- 变量表达式: ${…}
- 选择变量表达式: *{…}
- 信息表达式: #{…}
- URL连接表达式: @{…}
-
文字类型:
- 字符型: ‘one text’ , ‘Another one!’ ,…
- 数值型: 0 , 34 , 3.0 , 12.3 ,…
- Boolean型: true , false
- 空值: null
- 文本字符串: one , sometext , main ,…
- 字符串操作:
- 字符串连接: +
- 文字替换: |The name is ${name}|
- 数值型操作:
- 运算符: + , - , * , / , %
- 负号: -
- Boolean操作:
- 运算符: and , or
- 非运算符: ! , not
- 比较相等算法:
- 比较: > , < , >= , <= ( gt , lt , ge , le )
- 相等算法: == , != ( eq , ne )
-
条件语句:
- If-then: (if) ? (then)
- If-then-else: (if) ? (then) : (else)
- Default: (value) ?: (defaultvalue)
所有上面算法都可以随意组合和嵌套:
'User is of type ' + (${user.isAdmin()} ? 'Administrator': (${user.type} ?: 'Unknown'))
· 条件判断
(if) ? (then) if-then
(if) ? (then) : (else) if-then-else
<tr th:class="${row.even}? 'even' : 'odd'">
...
</tr>
条件表达式中的三个部分自身也可以是表达式,也可以是变量(${…}, *{…}), 消息(#{…}), URL (@{…}) 或字面量 (’…’)
条件表达式也可以使用括号来嵌套:
<tr th:class="${row.even}? (${row.first}? 'first' : 'even') : 'odd'">
...
</tr>
else表达式也可以省略,当条件为false时,会返回null:
<tr th:class="${row.even}? 'alt'">
...
</tr>
(value) ?: (defaultvalue) Default
只有在第一个表达式返回null时,第二个表达式才会运算
信息表达式
我们之前的例子是这样的
<p th:utext="#{home.welcome}">Welcome to our grocery store!</p>
home.welcome=欢迎光临本店,
但是有的时候我们需要在消息中增加变量,比如客人的名字怎么办?比如达到如下效果
<p>¡Bienvenido a nuestra tienda de comestibles, 木鱼!</p>
这样办:
home.welcome=欢迎光临本店, {0}!
<p th:utext="#{home.welcome(${session.user.name})}">
¡Bienvenido a nuestra tienda de comestibles, 木鱼!
</p>
在这里,参数可以是字符型也可是树数值型或者日期型。当然如果我们需要多个参数的话,类推即可,并且我们也可以内嵌表达式替换字符串,比如:
<p th:utext="#{${welcomeMsgKey}(${session.user.name})}">
Welcome to our grocery store, 木鱼!
</p>
变量表达式
变量表达式可以解析OGNL语法。详尽的语法信息可以访问官网:
http://commons.apache.org/ognl/
系统基本对象
OGNL有以下基本内置对象
- #ctx : the context
- #object. vars: the context variables.
- #locale : the context locale.
- #httpServletRequest : (only in Web Contexts)theHttpServletRequest object.
- #httpSession : (only in Web Contexts) the HttpSession object.
所以我们可以用如下方式引用:
Established locale country: <span th:text="${#locale.country}">US</span>.
Thymeleaf提供的对象
除了这些基本的对象,Thymeleaf将为我们提供一套实用的对象。来帮助我们我们执行常见的任务。
- #dates : 为 java.util.Date对象提供工具方法,比如:格式化,提取年月日等.
- #calendars : 类似于#dates , 但是只针对java.util.Calendar对象.
- #numbers : 为数值型对象提供工具方法。
- #strings :为String 对象提供工具方法。如: contains, startsWith, prepending/appending等。
- #objects : 为object 对象提供常用的工具方法。
- #bools : 为boolean 对象提供常用的工具方法。
- #arrays : 为arrays 对象提供常用的工具方法。
- #lists :为lists对象提供常用的工具方法。
- #sets : 为sets对象提供常用的工具方法。
- #maps : 为maps对象提供常用的工具方法。
- #aggregates :为创造一个arrays 或者 collections聚集函数提供常用的工具方法。
- #messages : utility methods for obtaining externalized messages inside variables expressions, in the same way as they would be obtained using #{…} syntax?.
- #ids : 为可能需要循环的ID属性提供常用的工具方法。
在我们的主页中重新格式化日期
现在我们知道了Thymeleaf提供的工具类和表达式的语法,那么我们来重新格式化首页的日期吧,首先在我们的controller层中吧字符型日期替换成对象
SimpleDateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy");
Calendar cal = Calendar.getInstance();
WebContext ctx = new WebContext(request, servletContext, request.getLocale());
ctx.setVariable("today", dateFormat.format(cal.getTime()));
templateEngine.process("home", ctx, response.getWriter());
替换成
WebContext ctx = new WebContext(request, servletContext, request.getLocale());
ctx.setVariable("today", Calendar.getInstance());
templateEngine.process("home", ctx, response.getWriter());
然后是模板
<p>
Today is: <span th:text="${#calendars.format(today,'dd MMMM yyyy')}">13 May 2011</span>
</p>
选择表达式用法(*{ })
变量不仅能用在#{ }上,还能用在* { }上。两者的区别在于* { }上的的变量首先是选定对象的变量。如果不选定对象,那么是整个上下文环境中的变量和#{ }相同
选择对象用什么呢?th:object标签属性。我们使用它在我们的用户配置文件(userprofile.html)页面:
<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>
<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>
如果一个对象已经被选择,即th:object=”${session.user}”。那么我们也使用#object对象去引用。
<div th:object="${session.user}">
<p>Name: <span th:text="${#object.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>
就像之前说的,如果没有对象被选中,那么#{ }和* { }表达式的意义是相同的。
<div>
<p>Name: <span th:text="*{session.user.name}">Sebastian</span>.</p>
<p>Surname: <span th:text="*{session.user.surname}">Pepper</span>.</p>
<p>Nationality: <span th:text="*{session.user.nationality}">Saturn</span>.</p>
</div>
URL链接
URL链接有以下几种类型:
- 绝对地址,如http://www.thymeleaf.org
- 相对地址
- 页面相对: user/login.html
- 上下文相对:/itemdetails?id=3 (服务器上下文名称会被自动添加)
- 服务器相对:~/billing/processInvoice(允许调用同一服务器上的另一个上下文中的URL)
让我们来使用th:href属性:
<!-- Will produce 'http://localhost:8080/gtvg/order/details?orderId=3' (plus rewriting) -->
<a href="details.html"
th:href="@{http://localhost:8080/gtvg/order/details(orderId=${o.id})}">view</a>
<!-- Will produce '/gtvg/order/details?orderId=3' (plus rewriting) -->
<a href="details.html" th:href="@{/order/details(orderId=${o.id})}">view</a>
<!-- Will produce '/gtvg/order/3/details' (plus rewriting) -->
<a href="details.html" th:href="@{/order/{orderId}/details(orderId=${o.id})}">view</a>
我来解释下:
- th:href属性修饰符:它将计算并替换使用href链接URL 值,并放入的href属性中。
- 我们可以使用URL参数的表达式(比如在orderId=${o.id} )
- 如果需要多个参数,这些将由逗号分隔,比如:@{/order/process(execId=${execId},execType=’FAST’)}
- 变量也允许URL路径中使用,比如:@{/order/{orderId}/details(orderId=${orderId})}
- URL中以”/“开头的路径(比如/order/details)将会加上服务器地址和域名。形成完整的URL
- th:href中可以直接使用静态地址。
URL可以用复杂的表达式:
<a th:href="@{${url}(orderId=${o.id})}">view</a>
<a th:href="@{'/details/'+${user.login}(orderId=${o.id})}">view</a>
现在我们知道如何创建链接的url,那么添加一个小菜单在我们的网站吧
<p>Please select an option</p>
<ol>
<li><a href="product/list.html" th:href="@{/product/list}">Product List</a></li>
<li><a href="order/list.html" th:href="@{/order/list}">Order List</a></li>
<li><a href="subscribe.html" th:href="@{/subscribe}">Subscribe to our Newsletter</a></li>
<li><a href="userprofile.html" th:href="@{/userprofile}">See User Profile</a></li>
</ol>
针对同服务器地址,不同域名的URL。可以这样写@{~/path/to/something}
基本类型操作
字符型
文本文字可以用单引号来包含。需要转义的话可以用\’转义
<p>
Now you are looking at a <span th:text="'working web application'">template file</span>.
</p>
数值型
数值型操作简单。如下所示:
<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型
boolean型不是true就是false:
<div th:if="${user.isAdmin()} == false"> ...
注意,在上面的例子中,= = false写在括号外,因此是Thymeleaf本身负责解析解析它。如果是写在括号内,它将由OGNL负责解析:
<div th:if="${user.isAdmin() == false}"> ...
Null型
<div th:if="${variable.something} == null"> ...
Literal tokens(不明白什么意思,大概是字符串文本)
Numeric, boolean 和 null都是字符串文本的一种类型。
只是使表达式更加简洁。工作时终将解析成字符串文本(‘。。。。。。’),但是他们有更多的限制,比如只能用数字(0~9),下划线,.,没有空格,没有逗号等等。
所以当我们仅仅用字符串的话,可以用这种:
<div th:class="content">...</div>
替换掉
<div th:class="'content'">...</div>
文本间连接
th:text="'The name of the user is ' + ${user.name}"
高级文本连接用法
我们可以用“|”包含住想要连接的文本,替换’…’ + ‘…’方式,这样就可以省心不少。
<span th:text="|Welcome to our application, ${user.name}!|">
替换原来的
<span th:text="'Welcome to our application, ' + ${user.name} + '!'">
高级点可以这样
<span th:text="${onevar} + ' ' + |${twovar}, ${threevar}|">
注意:${…}表达式可以被放在|….|之间,但是不能放在’….’之间哦
算术运算
也可以用一些算术运算符:+ , - , * , / , % .
th:with="isEven=(${prodStat.count} % 2 == 0)"
比较与相等
> , < , >= ,<=,== 和 !=都可以用,但是<,>这两个在必须转义。
th:if="${prodStat.count} > 1"
th:text="'Execution mode is ' + ( (${execMode} == 'dev')? 'Development' : 'Production')"
当然嫌转义什么的太麻烦小朋友,可以用别名替代 gt ( > ), lt ( < ), ge ( >= ), le ( <= ), not ( ! ), eq ( == ),neq / ne ( != ).
条件表达式
可以这样用
<tr th:class="${row.even}? 'even' : 'odd'">
...
</tr>
也可以这样中
<tr th:class="${row.even}? (${row.first}? 'first' : 'even') : 'odd'">
...
</tr>
可以省略false的返回值,当然如果false那么返回的是一个空值
<tr th:class="${row.even}? (${row.first}? 'first' : 'even') : 'odd'">
...
</tr>
默认表达式
默认表达式可以简化表达式,个人不建议用,阅读性差。如:
<div th:object="${session.user}">
...
<p>Age: <span th:text="*{age}?: '(no age specified)'">27</span>.</p>
</div>
解释一下:age如果是null的话就执行’(no age specified)’这段,否则就显示age。跟以下一样:
<p>Age: <span th:text="*{age != null}? *{age} : '(no age specified)'">27</span>.</p>
还可以嵌套玩:
<p>
Name:
<span th:text="*{firstName}?: (*{admin}? 'Admin' : #{default.username})">Sebastian</span>
</p>
预处理表达式
有的时候我们需要预处理一些信息到表达式中。比如某个变量的名字是变的,怎么办?预处理来了。
预处理表达式用 __${expression}__ 双下划线包裹,举个栗子:
我们在外部资源文件中配了这个属性:
article.text=@myapp.translator.Translator@translateToSpanish({0})
我们可以在模板中表达式是这样子的:
<p th:text="${__#{article.text('textVar')}__}">Some text here...</p>
那么引擎会首先从资源文件中获取article.text的值,再执行它。
<p th:text="${@myapp.translator.Translator@translateToFrench(textVar)}">Some text here...</p>
双下划线可以用\_\_转义
设置属性值
th:attr 任何属性值<form action="subscribe.html" th:attr="action=@{/subscribe}">
<fieldset>
<input type="text" name="email" />
<input type="submit" value="Subscribe me!" th:attr="value=#{subscribe.submit}"/>
</fieldset>
</form>
多个属性一起设置,用逗号隔开
<img src="../../images/gtvglogo.png" th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />
设置指定属性
th:abbr th:accept th:accept-charset
th:accesskey th:action th:align
th:alt th:archive th:audio
th:autocomplete th:axis th:background
th:bgcolor th:border th:cellpadding
th:cellspacing th:challenge th:charset
th:cite th:class th:classid ...
<input type="submit" value="Subscribe me!" th:value="#{subscribe.submit}"/>
<form action="subscribe.html" th:action="@{/subscribe}">
<li><a href="product/list.html" th:href="@{/product/list}">Product List</a></li>
设置多个属性在同一时间 有两个特殊的属性可以这样设置: th:alt-title 和 th:lang-xmllang
th:alt-title 设置 alt 和 title
th:lang-xmllang 设置 lang 和 xml:lang
<img src="../../images/gtvglogo.png" th:attr="src=@{/images/gtvglogo.png},title=#{logo},alt=#{logo}" />
<img src="../../images/gtvglogo.png"th:src="@{/images/gtvglogo.png}" th:title="#{logo}" th:alt="#{logo}" />
<img src="../../images/gtvglogo.png"th:src="@{/images/gtvglogo.png}" th:alt-title="#{logo}" />
前置和后置添加属性值 th:attrappend 和 th:attrprepend
<input type="button" value="Do it!" class="btn" th:attrappend="class=${' ' + cssStyle}" />
编译后:
<input type="button" value="Do it!" class="btn warning" />
还有两个特定的添加属性 th:classappend 和 th:styleappend
<tr th:each="prod : ${prods}" class="row" th:classappend="${prodStat.odd}? 'odd'">
修复的布尔属性
<input type="checkbox" name="active" th:checked="${user.active}" />
所有修复的布尔属性:
|th:async |th:autofocus |th:autoplay |
|th:checked |th:controls |th:declare |
|th:default |th:defer |th:disabled |
|th:formnovalidate|th:hidden |th:ismap |
|th:loop |th:multiple |th:novalidate |
|th:nowrap |th:open |th:pubdate |
|th:readonly |th:required |th:reversed |
|th:scoped |th:seamless |th:selected |
HTML5友好的属性及元素名
<table>
<tr data-th-each="user : ${users}">
<td data-th-text="${user.login}">...</td>
<td data-th-text="${user.name}">...</td>
</tr>
</table>
data-{prefix}-{name}是编写HTML5自定义属性的标准语法,不需要开发者使用th:*这样的命名空间,Thymeleaf让这种语法自动对所有dialect都可用。
遍历
·基础:
<tr th:each="prod : ${prods}">
<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>
可遍历的对象:实现java.util.Iterable、java.util.Map(遍历时取java.util.Map.Entry)、array、任何对象都被当作只有对象自身一个元素的列表
·状态
- 当前遍历索引,从0开始,index属性
- 当前遍历索引,从1开始,count属性
- 总元素数量,size属性
- 每一次遍历的iter变量,current属性
- 当前遍历是even还是odd,even/odd布尔属性
- 当前遍历是第一个,first布尔属性
- 当前遍历是最后一个,last布尔属性
<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>
若不指定状态变量,Thymeleaf会默认生成一个名为“变量名Stat”的状态变量:
<tr th:each="prod : ${prods}" th:class="${prodStat.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>