Thymeleaf快速入门
Thymeleaf 入门
1. 简单表达式
1.1 外部化文本 #{---}
外部化文本是从模板文件中提取模板代码的片段,以便它们可以保存在单独的文件(通常为 .properties
文件)中,并且可以轻松地替换为使用其他语言编写的等效文本(称为国际化或简单的i18n) 。文本的外部化片段通常称为“消息(messages)”。
<p th:text="#{home.welcome}">Welcome to our grocery store!</p>
1.2 变量表达式 ${---}
变量表达式有丰富的内置方法,使其更强大,更方便。
1.2.1 变量表达式功能
(1)可以获取对象的属性和方法
(2)可以使用ctx,vars,locale,request,response,session,servletContext内置对象
(3)可以使用dates,numbers,strings,objects,arrays,lists,sets,maps等内置方法(重点介绍)
1.2.2 常用的内置对象
#ctx:上下⽂对象。
#vars:上下⽂变量。
#locale:上下⽂区域设置。
#request :(仅在Web Contexts中)HttpServletRequest对象。
#response:(仅在Web上下⽂中)HttpServletResponse对象。
#session :(仅在Web上下⽂中)HttpSession对象。
#servletContext :(仅在Web上下⽂中)ServletContext对象。
1.2.3 常用的内置方法
一、strings:字符串格式化方法,常用的Java方法它都有。
比如:equals,equalsIgnoreCase,length,trim,toUpperCase,toLowerCase,indexOf,substring,replace,startsWith,endsWith,contains,containsIgnoreCase等
二、numbers:数值格式化方法。
常用的方法有:formatDecimal等
三、bools:布尔方法。
常用的方法有:isTrue,isFalse等
四、arrays:数组方法。
常用的方法有:toArray,length,isEmpty,contains,containsAll等
五、lists,sets:集合方法。
常用的方法有:toList,size,isEmpty,contains,containsAll,sort等
六、maps:对象方法。
常用的方法有:size,isEmpty,containsKey,containsValue等
七、dates:日期方法。
常用的方法有:format,year,month,hour,createNow等
1.2.4 示例
@RequestMapping("varexpressions")
public String varexpressions(ModelMap map) {
map.put("itdragonStr", "itdragonBlog");
map.put("itdragonBool", true);
map.put("itdragonArray", new Integer[]{1,2,3,4});
map.put("itdragonList", Arrays.asList(1,3,2,4,0));
Map itdragonMap = new HashMap();
itdragonMap.put("thName", "${#...}");
itdragonMap.put("desc", "变量表达式内置方法");
map.put("itdragonMap", itdragonMap);
map.put("itdragonDate", new Date());
map.put("itdragonNum", 888.888D);
return "grammar/varexpressions";
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>ITDragon Thymeleaf 内置方法</title>
</head>
<body>
<h2>ITDragon Thymeleaf 内置方法</h2>
<h3>#strings </h3>
<div th:if="${not #strings.isEmpty(itdragonStr)}" >
<p>Old Str : <span th:text="${itdragonStr}"/></p>
<p>toUpperCase : <span th:text="${#strings.toUpperCase(itdragonStr)}"/></p>
<p>toLowerCase : <span th:text="${#strings.toLowerCase(itdragonStr)}"/></p>
<p>equals : <span th:text="${#strings.equals(itdragonStr, 'itdragonblog')}"/></p>
<p>equalsIgnoreCase : <span th:text="${#strings.equalsIgnoreCase(itdragonStr, 'itdragonblog')}"/></p>
<p>indexOf : <span th:text="${#strings.indexOf(itdragonStr, 'r')}"/></p>
<p>substring : <span th:text="${#strings.substring(itdragonStr, 2, 8)}"/></p>
<p>replace : <span th:text="${#strings.replace(itdragonStr, 'it', 'IT')}"/></p>
<p>startsWith : <span th:text="${#strings.startsWith(itdragonStr, 'it')}"/></p>
<p>contains : <span th:text="${#strings.contains(itdragonStr, 'IT')}"/></p>
</div>
<h3>#numbers </h3>
<div>
<p>formatDecimal 整数部分随意,小数点后保留两位,四舍五入: <span th:text="${#numbers.formatDecimal(itdragonNum, 0, 2)}"/></p>
<p>formatDecimal 整数部分保留五位数,小数点后保留两位,四舍五入: <span th:text="${#numbers.formatDecimal(itdragonNum, 5, 2)}"/></p>
</div>
<h3>#bools </h3>
<div th:if="${#bools.isTrue(itdragonBool)}">
<p th:text="${itdragonBool}"></p>
</div>
<h3>#arrays </h3>
<div th:if="${not #arrays.isEmpty(itdragonArray)}">
<p>length : <span th:text="${#arrays.length(itdragonArray)}"/></p>
<p>contains : <span th:text="${#arrays.contains(itdragonArray, 5)}"/></p>
<p>containsAll : <span th:text="${#arrays.containsAll(itdragonArray, itdragonArray)}"/></p>
</div>
<h3>#lists </h3>
<div th:if="${not #lists.isEmpty(itdragonList)}">
<p>size : <span th:text="${#lists.size(itdragonList)}"/></p>
<p>contains : <span th:text="${#lists.contains(itdragonList, 0)}"/></p>
<p>sort : <span th:text="${#lists.sort(itdragonList)}"/></p>
</div>
<h3>#maps </h3>
<div th:if="${not #maps.isEmpty(itdragonMap)}">
<p>size : <span th:text="${#maps.size(itdragonMap)}"/></p>
<p>containsKey : <span th:text="${#maps.containsKey(itdragonMap, 'thName')}"/></p>
<p>containsValue : <span th:text="${#maps.containsValue(itdragonMap, '#maps')}"/></p>
</div>
<h3>#dates </h3>
<div>
<p>format : <span th:text="${#dates.format(itdragonDate)}"/></p>
<p>custom format : <span th:text="${#dates.format(itdragonDate, 'yyyy-MM-dd HH:mm:ss')}"/></p>
<p>day : <span th:text="${#dates.day(itdragonDate)}"/></p>
<p>month : <span th:text="${#dates.month(itdragonDate)}"/></p>
<p>monthName : <span th:text="${#dates.monthName(itdragonDate)}"/></p>
<p>year : <span th:text="${#dates.year(itdragonDate)}"/></p>
<p>dayOfWeekName : <span th:text="${#dates.dayOfWeekName(itdragonDate)}"/></p>
<p>hour : <span th:text="${#dates.hour(itdragonDate)}"/></p>
<p>minute : <span th:text="${#dates.minute(itdragonDate)}"/></p>
<p>second : <span th:text="${#dates.second(itdragonDate)}"/></p>
<p>createNow : <span th:text="${#dates.createNow()}"/></p>
</div>
</body>
</html>
1.3 选择表达式 *{---}
<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
指定的执行对象,也可⽤于${---}
表达式:
<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>
1.4 链接表达式 @{---}
首先来认识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是⼀个修饰符属性:⼀旦处理,它将计算要使⽤的链接URL,并将该值设置为标签的href属性。
- 我们被允许使⽤表达式的URL参数(可以在
orderId = $ {o.id}
中看到)。所需的URL参数编码操作也将⾃动执⾏。 - 如果需要⼏个参数,这些参数将以逗号分隔:
@ {/ order /process(execId = $ {execId},execType ='FAST')}
- URL路径中也允许使⽤变量模板:
@ {/ order / {orderId} /details(orderId = $ {orderId})}
- 以/开头的相对URL(例如:
/ order / details
)将⾃动以应⽤程序上下⽂名称为前缀。 - 如果cookie未启⽤或尚未知道,则可能会在相对URL中添加
“;jsessionid = ...”
后缀,以便会话被保留。这被称为URL重写,Thymeleaf允许您使⽤Servlet API中的每个URL的response.encodeURL(...)
机制来插⼊⾃⼰的重写过滤器。 th:href
属性允许我们(可选地)在我们的模板中有⼀个⼯作的静态href属性,这样当我们直接打开原型设计时,我们的模板链接可以被浏览器导航。
与消息语法(#{—})的情况⼀样,URL基数也可以是计算另⼀个表达式的结果:
<a th:href="@{${url}(orderId=${o.id})}">view</a>
<a th:href="@{'/details/'+${user.login}(orderId=${o.id})}"
>view</a>
1.4.1 主⻚菜单
我们知道如何创建链接⽹址,如何在⽹站的其他⼀些⻚⾯中添加⼀个⼩菜单呢?
<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>
1.4.2 服务器相对URL
可以使⽤附加语法来创建服务器根⽬录(⽽不是上下⽂相对)URL,以链接到同⼀服务器中的不同上下⽂。 这些URL将被指定为@ {〜/path/to/something}
1.5 表达式支持的语法
字面(Literals)
- 文本文字(Text literals):
'one text', 'Another one!',…
- 数字文本(Number literals):
0, 34, 3.0, 12.3,…
- 布尔文本(Boolean literals):
true, false
- 空(Null literal):
null
- 文字标记(Literal tokens):
one, sometext, main,…
文本操作(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)
- 等值运算符(Equality operators):
==, != (eq, ne)
条件运算符(Conditional operators)
- If-then:
(if) ? (then)
- If-then-else:
(if) ? (then) : (else)
- Default: (value) ?:
(defaultvalue)
1.6 代码块表达式
2. 常用Th属性
html
有的属性,Thymeleaf
基本都有,而常用的属性大概有七八个。其中th属性
执行的优先级从1~8,数字越低优先级越高。
2.1 th:id
替换id属性
示例:
<input th:id="'xxx' + ${collect.id}"/> //collect.id = 001
等价于:
<input id="xxx001"/>
2.2 th:text
body文本替换
示例:
<p th:text="${collect.description}">description</p> //collect.description = very good!
等价于:
<p>very good!</p>
2.3 th:utext
body文本替换(非格式转换)
示例:
<div th:utext = "${collection.htmlStr}"></div>
//collection.htmlStr = "<h2>这是标题2</h2>"
等价于:
<div><h2>这是标题2</h2></div>
2.4 th:object
替换对象
2.5 th:attr
设置标签属性
2.6 th:value
设置当前元素的value值
2.7 th:href
设置当前元素的 链接地址
2.8 th:src
图片类地址引入
2.9 th:if
条件判断
示例:
<div th:if="${num} gt 2" >情景一</div> //num = 3
<div th:if="${num} lt 2" >情景二</div>
比较运算符:
gt:great than(大于)>
ge:great equal(大于等于)>=
eq:equal(等于)==
lt:less than(小于)<
le:less equal(小于等于)<=
ne:not equal(不等于)!=
等价于:
<div>情景一</div>
2.10 th:unless
条件判断,与th:if
相反
2.11 th:switch
条件判断,与th:case
配合使用
<div th:switch="${collection.enable}">
<p th:case="0">情景1</p>
<p th:case="1">情景2</p>
<p th:case="2">情景3</p>
</div>
若collection.enable = 2
,则可就等价于:
<div><p>情景3</p></div>
2.12 th:each
遍历循环元素
示例:
<table>
<tr th:each="user:${userlist}">
<td th:text="${user.id}"></td>
<td th:text="${user.username}"></td>
<td th:text="${user.password}"></td>
<td th:text="${user.petname}"></td>
</tr>
</table>
如果userList
为:
1,libai,001,小1
2,lanlw,002,小2
2,sulie,003,小3
等价于:
<table>
<tr>
<td >1</td>
<td >libai</td>
<td >001</td>
<td>小1</td>
</tr>
<tr>
<td >2</td>
<td >lanlw</td>
<td >001</td>
<td>小2</td>
</tr>
<tr>
<td >3</td>
<td >sulie</td>
<td >001</td>
<td>小3</td>
</tr>
</table>
2.13 th:style
设置样式
2.14 th:fragment
定义一个代码片段,方便其它地方引用
2.15 th:insert
,th:replace
和 th:include
代码块引入
关于thymeleaf th:replace th:include th:insert 的区别
th:insert :保留自己的主标签,保留th:fragment的主标签。
th:replace :不要自己的主标签,保留th:fragment的主标签。
th:include :保留自己的主标签,不要th:fragment的主标签。(官方3.0后不推荐)
示例:
//需要替换的片段内容:
<footer th:fragment="copy">
<script type="text/javascript" th:src="@{/plugins/jquery/jquery-3.0.2.js}"></script>
</footer>
//导入片段:
<div th:insert="footer :: copy"></div>
<div th:replace="footer :: copy"></div>
<div th:include="footer :: copy"></div>
//结果为:
<div>
<footer>
<script type="text/javascript" th:src="@{/plugins/jquery/jquery-3.0.2.js}"></script>
</footer>
</div>
<footer>
<script type="text/javascript" th:src="@{/plugins/jquery/jquery-3.0.2.js}"></script>
</footer>
<div>
<script type="text/javascript" th:src="@{/plugins/jquery/jquery-3.0.2.js}"></script>
</div>
2.15 th:remove
删除模板片段
th:remove
的值如下:
1.all:删除包含标签和所有的孩子。
2.body:不包含标记删除,但删除其所有的孩子。
3.tag:包含标记的删除,但不删除它的孩子。
4.all-but-first:删除所有包含标签的孩子,除了第一个。
5.none:什么也不做。这个值是有用的动态评估。
示例:
<table>
<tr th:each="number : ${#numbers.sequence(0, 5)}">
<td th:remove="none">
<span th:text="|user-| + ${number}"></span>***
<span th:text="${number}"></span>
</td>
</tr>
</table>
- 如果
th:remove
取值为all
,则会删除td以及其子元素 - 取值为
body
时,将td下的全部子元素删除 - 取值为
tag
,会删除td,不会删除两个span。 - 取值为
all-but-first
,删除自己下面全部子元素,不删除第一个 - 取值为
none
,不进行任何操作。
3. Thymeleaf
在SpringBoot
中的使用
spring.thymeleaf.cache = true 启用模板缓存(开发时建议关闭)
spring.thymeleaf.check-template = true 检查模板是否存在,然后再呈现
spring.thymeleaf.check-template-location = true 检查模板位置是否存在
spring.thymeleaf.content-type = text/html Content-Type值
spring.thymeleaf.enabled = true 启用MVC Thymeleaf视图分辨率
spring.thymeleaf.encoding = UTF-8 模板编码
spring.thymeleaf.excluded-view-names = 应该从解决方案中排除的视图名称的逗号分隔列表
spring.thymeleaf.mode = HTML5 应用于模板的模板模式。另请参见StandardTemplateModeHandlers
spring.thymeleaf.prefix = classpath:/templates/ 在构建URL时预先查看名称的前缀
spring.thymeleaf.suffix = .html 构建URL时附加查看名称的后缀
spring.thymeleaf.template-resolver-order = 链中模板解析器的顺序
spring.thymeleaf.view-names = 可以解析的视图名称的逗号分隔列表