目录
https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#introducing-thymeleaf
引入 Thymeleaf
使用 Thymeleaf
Thymeleaf 语法
常用属性
标准表达式语法
${}
*{...}
#{}
@{}
~{}
示例演示
声明与引入公共片段
迭代 th:each
迭代使用
迭代状态
条件判断
显示标签体内容
th:object 直接取出对象
Spring Boot 官方不推荐使用JSP,因为内嵌的 Tomcat 、Jetty 容器不支持以 jar 形式运行 JSP。Spring Boot
中提供了大量模板引擎,包含 Freemarker、Mastache、Thymeleaf 等。 而 Spring Boot 官方推荐使用
Thymeleaf 作为模板引擎, 因为 Thymeleaf 提供了完美的 SpringMVC 的支持。
这是一张烂大街的图,说明模板引擎的作用是什么,把数据和模板整合成展示给用户的页面。
https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#introducing-thymeleaf
引入 Thymeleaf
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
使用 Thymeleaf
模板文件放在哪里?
将 HTML 页面放到 classpath:/templates/ 目录下, Thymeleaf 就能自动渲染。
示例:
@RequestMapping(value = "execute", method = RequestMethod.GET)
public String execute(Map<String,Object> map) {
map.put("name","haogenmin");
return "success";
}
发送 http://localhost:8080/execute 后, 通过上面代码转到 classpath:/templates/success.html
创建success.html文件:
在 html 页面加上以下名称空间 , 使用 Thymeleaf 时就有语法提示。
<html xmlns:th="http://www.thymeleaf.org">
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>success!!!!</p>
<p th:text="${name}">名字</p>
</body>
</html>
结果:
Thymeleaf 语法
常用属性
优先级 | 属性名 | 作用 |
1 | th:insert th:replace | 引入片段,与 th:fragment 声明组合使用; 类似于 jsp:include |
2 | th:each | 遍历 , 类似于 c:forEach |
3 | th:if th:unless th:switch th:case | 条件判断 , 类似于 c:if |
4 | th:object th:with | 声明变量 , 类似于 c:set |
5 | th:attr th:attrprepend th:attrappend | 修改任意属性 , prepend 前面追加 , append后面追加 |
6 | th:value th:href th:src ... | 修改任意html原生属性值 |
7 | th:text th:utext | 修改标签体中的内容 , th:text 转义特殊字符 , 即 h1 标签以文本显示出来 th:utext 是不转义特殊字符 , 即 h1 标签展现出本来效果 |
8 | th:fragment | 声明片段 |
9 | th:remove | 移除片段 |
标准表达式语法
https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#variables
- 变量表达式:
${...}
- 选择变量表达式:
*{...}
- 消息表达:
#{...}
- 链接URL表达式:
@{...}
- 片段表达式:
~{...}
文字
- 文本文字:
'one text'
,'Another one!'
,... - 号码文字:
0
,34
,3.0
,12.3
,... - 布尔文字:
true
,false
- 空文字:
null
- 文字标记:
one
,sometext
,main
,...
文字操作:
- 字符串串联:
+
- 文字替换:
|The name is ${name}|
算术运算:
- 二元运算符:
+
,-
,*
,/
,%
- 减号(一元运算符):
-
布尔运算:
- 二元运算符:
and
,or
- 布尔否定(一元运算符):
!
,not
比较和平等:
- 比较:
>
,<
,>=
,<=
(gt
,lt
,ge
,le
) - 等号运算符:
==
,!=
(eq
,ne
)
条件运算符:
- 如果-则:
(if) ? (then)
- 如果-则-否则:
(if) ? (then) : (else)
- 默认:
(value) ?: (defaultvalue)
特殊令牌:
- 无操作:
_
我们已经提到过,${...}
表达式实际上是在上下文中包含的变量映射上执行的OGNL(对象图导航语言)表达式。
在启用Spring MVC的应用程序中,OGNL将替换为SpringEL,但是其语法与OGNL的语法非常相似(实际上,对于大多数常见情况而言,它们是完全相同的)。
${}
1、在上下文变量上评估OGNL表达式时,某些对象可用于表达式,以提高灵活性。这些对象(根据OGNL标准)将以#
符号开头进行引用:
-
#ctx
:上下文对象。 -
#vars:
上下文变量。 -
#locale
:上下文语言环境。 -
#request
:(仅在Web上下文中)HttpServletRequest
对象。 -
#response
:(仅在Web上下文中)HttpServletResponse
对象。 -
#session
:(仅在Web上下文中)HttpSession
对象。 -
#servletContext
:(仅在Web上下文中)ServletContext
对象。
因此,我们可以这样做:
<span th:text="${#locale.country}">US</span>
2、使用内置的工具对象
-
#execInfo
:有关正在处理的模板的信息。 -
#messages
:用于获取变量表达式内的外部化消息的方法,与使用#{…}语法获得消息的方法相同。 -
#uris
:用于转义部分URL / URI的方法 -
#conversions
:用于执行已配置的转换服务(如果有)的方法。 -
#dates
:java.util.Date
对象的方法:格式化,组件提取等。 -
#calendars
:类似于#dates
,但用于java.util.Calendar
对象。 -
#numbers
:格式化数字对象的方法。 -
#strings
:String
对象的方法:包含,startsWith,前置/追加等。 -
#objects
:一般对象的方法。 -
#bools
:布尔值评估的方法。 -
#arrays
:数组方法。 -
#lists
:列表方法。 -
#sets
:套方法。 -
#maps
:地图方法。 -
#aggregates
:用于在数组或集合上创建聚合的方法。 -
#ids
:用于处理可能重复的id属性的方法(例如,由于迭代的结果)。
*{...}
<div th:object="${session.user}">
省得每次写${session.user.fifirstName}, 直接取出对象,然后写对象名即可
<p>Name: <span th:text="*{fifirstName}">Sebastian</span> </p>
<p>Email: <span th:text="*{email}">Saturn</span> </p>
</div>
#{}
Message Expressions(获取国际化内容)
@{}
定义url
~{}
片段引用表达式
<div th:insert="~{commons :: main}">...</div>
示例演示
声明与引入公共片段
header.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div th:fragment="header_common">
这是th:fragment声明公共片段
</div>
<div id="header_common_id">
这是id选择器声明公共片段
</div>
</body>
</html>
success.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>success!!!!</p>
<p th:text="${name}">名字</p>
<!--方式1:
header : 公共片段所在模板的文件名
header_common :声明代码片段名
-->
<div th:replace="header :: header_common"></div>
<!--方式1:
header : 公共片段所在模板的文件
#header_common_id: 声明代码片的id值
-->
<div th:replace="header :: #header_common_id"></div>
<!--
th:insert 和 th:replace的区别
th:insert和th:replace都可以引入片段,两者的区别在于
th:insert: 保留引入时使用的标签
th:replace:不保留引入时使用的标签, 将声明片段直接覆盖当前引用标签
-->
<h2 th:insert="header :: #header_common_id"></h2>
</body>
</html>
迭代 th:each
迭代使用
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body >
<table th:border="1px" >
<tr>
<th>
姓名
</th>
</tr>
<tr th:each="user : ${userlist}">
<!-- 方式一-->
<!-- 作用在不同的标签上,每次迭代生成一个子标签-->
<td th:text="${user}">
haogenmin
</td>
</tr>
</table>
<hr/>
<ul>
<!--方式2:-->
<!--作用在同一个标签上, 每次迭代生成一个当前标签-->
<li th:each="user : ${userlist}" th:text="${user}"></li>
</ul>
</body>
</html>
迭代状态
<table border="1px">
<tr>
<th>编号</th>
<th>姓名</th>
<th>性别</th>
<th>总记录数</th>
<th>偶数/奇数</th>
<th>第一个元素</th>
<th>最后一个元素</th>
</tr>
<!--
user : 第1个值,代表每次迭代出对象,名字任意取
iterStat : 第2个值,代表每次迭代器内置对象, 名字任意取, 并有如下属性:
index : 当前迭代下标 0 开始
count : 当前迭代下标 1 开始
size : 获取总记录数
current : 当前迭代出的对象
even/odd : 当前迭代是偶数还是奇数 (1开始算,返回布尔值)
first : 当前是否为第一个元素
last : 当前是否为最后一个元素
-->
<!--th:each作用在哪个标签上面,对应的就会根据它的值迭代多少次-->
<tr th:each="user,iterStat :${userlist}">
<td th:text="${iterStat.count}">111</td>
<td th:text="${user.userName}">111</td>
<td th:text="${user.gender == 2 ? '女' : '男'}">未知</td>
<td th:text="${iterStat.size}"></td>
<td th:text="${iterStat.even ? '偶数' : '奇数'}"></td>
<td th:text="${iterStat.first}"></td>
<td th:text="${iterStat.last}"></td>
</tr>
</table>
条件判断
th:if 不仅判断返回为 true 的表达式,还判断一些特殊的表达式。
如果值不是 Null, 以下情况均返回 true :
- 如果值是boolean类型并且值为true.
- 如果值是数值类型并且值不为0.
- 如果值是字符类型并且值不为空.
- 如果值是字符串并且内容不为 “false” , “offff” 或者 “no” .
- 如果值不是上述类型也返回true.
如果值是 NULL, 则返回 false
th:unless 与 th:if正好相反;
<!--th:if如果值为true,则显示出该 标签,否则 不显示
${#lists.isEmpty(userList)} true 说明 userList 是空 not false
${#lists.isEmpty(userList)} false 说明 userList 不是空的 not true
-->
<h3 th:if="not ${#lists.isEmpty(userlist)}">显示出来则userList集合不是空的</h3>
<h3 th:unless="${#lists.isEmpty(userlist)}">显示出来则userList集合不是空的</h3>
th:swith th:case 的作用大家都知道,看一下用法。
@RequestMapping(value = "user", method = RequestMethod.GET)
public String user(Map<String, Object> map) {
List<User> userList = new ArrayList<>();
userList.add(new User("张三",1));
userList.add(new User("翠花",2));
userList.add(new User("老王",1));
map.put("userlist", userList);
map.put("sex",2);
map.put("man",1);
return "user";
}
<div th:switch="${sex}">
<p th:case="2">女</p>
<!--获取man值与sex对比-->
<p th:case="${man}">男</p>
<!--如果上面均不满足,取下面默认值-->
<p th:case="*">未知</p>
</div>
显示标签体内容
- th:text 转义特殊字符, 即 h1标签以文本显示出来
- th:utext 不转义特殊字符, 即 h1 标签展现出本来效果
map.put("message", "SpringBoot <h1>真好玩!</h1>");效果
<hr/>
<div th:text="${message}"></div>
<!--不转义特殊字符,直接显示出应该有的效果-->
<div th:utext="${message}"></div>
补充:Thymeleaf 行内表达式双中括号: [[表达式]] (就是不在标签上使用属性)
<input type="checkbox" /> [[${message}]]
<p>Hello, [[${message}]] 。。。</p>
th:object 直接取出对象
request.getSession().setAttribute("user",new User("小胖",1));
<br/>
<!--th:object获取${session.user}对象-->
<div th:object="${session.user}">
<!--上面已经将对象获取出来了,下面直接写属性名即可获取到值-->
<p> 姓名:<span th:text="*{userName}"></span></p>
<p> 性别:<span th:text="*{gender == 2 ? '女' : '男'}"></span></p>
</div>