Thymeleaf 模板引擎使用
模板引擎是为了使用户看到的页面与业务数据(内容)分离而产生的一种模板技术,它可以生成特定格式的文档,用于网站的模板引擎会生产出标准的 HTML 静态页面内容。在 Java Web 开发技术栈中,常见的模板引擎有 FreeMarker、Velocity、Thymeleaf 等,JSP 也可以理解为一种模板引擎技术。Thymeleaf 官方学习文档为:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html。
入门使用
?? SpringBoot 引入 Thymeleaf 依赖
org.springframework.boot
spring-boot-starter-thymeleaf
?? 在 application.properties 进行 Thymeleaf 配置
# 页面缓存设置,默认值为 true(开发中方便调试设置为 false,上线稳定后应保持默认 true)
spring.thymeleaf.cache=false
# 模板编码,默认值为 UTF-8
spring.thymeleaf.encoding=UTF-8
# 指定模板页面的存放路径,默认值为 classpath:/templates/
spring.thymeleaf.prefix=classpath:/templates/
# 指定模板页面名称的后缀,默认值为 .html
spring.thymeleaf.suffix=.html
# 指定文本类型,默认值为 text/html
spring.thymeleaf.servlet.content-type=text/html
# 应用于模板的模板模式,默认值为 HTML
spring.thymeleaf.mode=HTML
?? 创建模板文件
在 resources/templates 目录新建模板文件 test.html,新增文件后,首先在模板文件的标签中导入 Thymeleaf 的名称空间:
导入该名称空间主要是为了 Thymeleaf 的语法提示和 Thymeleaf 标签的使用,最终的模板文件如下:
Thymeleaf Test
显示测试字段
?? 编辑 Controller 代码
@Controller
public class ThymeleafController {
@GetMapping("/hello")
public String hello(Model model) {
model.addAttribute("test", "这里是一个测试!");
return "test";
}
}
?? 启动并访问
访问localhost:8080/hello
,可以看到原本的标签中的内容已经被替换为
这里是一个测试!
:
上述模板中读取动态数据并渲染的语句如下:
显示测试字段
该模板语句中包含三块内容:
- html 标签
- Thymelaf 模板引擎的 th 标签
- Thymelaf 表达式
前半部分的为 html 的标签,后半部分为 Thymeleaf 属性标签和表达式语法。
th:text
表示文本替换,${test}
表示读取后台设置的 test 字段,该模板语句的作用就是动态的将标签中的内容替换为后台设置的 test 字段内容。
Thymeleaf 模板文件的编写规则如下:
- 任意的 Thymeleaf 属性标签
th:*
需要写在 html 标签体中(th:block
除外) - Thymleaf 表达式写在 Thymeleaf 属性标签中
th:* 替换属性值
前面我们使用th:text
进行文本替换,除此之外还提供了其他的标签属性来替换 HTML5 原生属性的值,具体信息可以查看 thymeleaf-attributes。下面介绍一下通过 Thymeleaf 语法修改属性值,代码如下:
?? 编辑 test.html 模板文件
Thymeleaf Test
text 标签
th:text 标签演示
th:utext 标签演示
id、name、value 标签
class、href 标签
链接
?? 编辑 Controller 代码
@Controller
public class ThymeleafController {
@GetMapping("/hello")
public String hello(Model model) {
model.addAttribute("th_text", "thymeleaf-text");
model.addAttribute("th_utext", "thymeleaf-utext");
model.addAttribute("th_id", "thymeleaf-id");
model.addAttribute("th_name", "thymeleaf-name");
model.addAttribute("th_value", "thymelaf-value");
model.addAttribute("th_class", "thymeleaf-class");
model.addAttribute("th_href", "https://www.baidu.com");
return "test";
}
}
? 启动并访问
访问localhost:8080/hello
,网页显示:
Thymeleaf Test
id、name、value 标签
class、href 标签
链接
Thymeleaf 语法规则
Thymleaf 官方对标准表达式特性总结如下,具体可以查看 Standard Expression Syntax。
-
表达式语法
- 变量表达式:
${...}
- 选择表达式:
*{...}
- 信息表达式:
#{...}
- 链接 URL 表达式:
@{...}
- 分段表达式:
~{...}
- 变量表达式:
-
字面量
- 字符串: 'one text', 'Another one!' ...
- 数字:
0
,34
,3.0
,12.3
... - 布尔值:
true
,false
- Null 值:
null
- 字面量标记:
one
,sometext
,main
...
-
文本运算
- 字符串拼接:
+
- 字面量置换:
|The name is ${name}|
- 字符串拼接:
-
算术运算
- 二元运算符:
+
,-
,*
,/
,%
- 负号(一元运算符): (unary operator):
-
- 二元运算符:
-
布尔运算
- 二元运算符:
and
,or
- 布尔非(一元运算符):
!
,not
- 二元运算符:
-
比较运算
- 比较:
>
,<
,>=
,<=
(gt
,lt
,ge
,le
) - 相等运算符:
==
,!=
(eq
,ne
)
比较运算符也可以使用转义字符,比如大于号,所以 Thymeleaf 语法中
>
等价于>
。 - 比较:
-
条件运算符
- If-then:
(if) ? (then)
- If-then-else:
(if) ? (then) : (else)
- Default:
(value) ?: (defaultvalue)
- If-then:
-
特殊语法
- 无操作:
_
- 无操作:
简单语法使用
下面主要介绍字面量及简单的运算操作,包括字符串、数字、布尔值等常用的字面量及常用的运算和拼接操作,代码如下:
?? 编辑 test.html 模板文件
Thymeleaf Test
基本类型操作(字符串):
一个简单的字符串:default text.
字符串连接:default text.
字符串连接:default text.
基本类型操作(数字):
一个简单的数字:1000.
算术运算: 2019 + 1 = 0.
算术运算: 14 - 1 = 0.
算术运算: 673 * 3=0.
算术运算: 39 ÷ 3=0.
基本类型操作(布尔值):
一个简单的数字比较:2019 > 2018,结果为:false.
字符串比较:thymeleafText == 'hello world',结果为:false.
数字比较:13 == 39 / 3,结果为:false.
?? 编辑 Controller 代码
@Controller
public class ThymeleafController {
@GetMapping("/hello")
public String hello(Model model) {
model.addAttribute("thymeleafText", "hello world");
model.addAttribute("number1", 2019);
model.addAttribute("number2", 3);
return "test";
}
}
?? 启动并访问
访问localhost:8080/hello
,网页显示:
变量表达式${}
变量表达式即 OGNL 表达式或 Spring EL 表达式,作用是获取模板中与后端返回数据所绑定对象的值,写法为 ${...}
,这是最常见的一个表达式,在取值赋值、逻辑判断、循环语句中都可以使用该表达式。
简单使用
变量表达式可以是 OGNL 表达式,${...}
不但可以访问基本数据类型的变量值,还可以访问对象的属性值,示例如下:
${person.father.name}
${person['father']['name']}
${countriesByCode.ES}
${personsByName['Jim'].age}
${personsArray[0].name}
${person.createCompleteName()}
${person.createCompleteNameWithSeparator('-')}
下面使用变量表达式${...}
获取后端返回的对象、数组和集合属性值,代码如下:
?? 编辑 test.html 模板文件
Thymeleaf Test
访问普通属性
name:Alice
name:Alice
name:Alice
访问数组和 List 集合
hobbies1:singing
hobbies2:singing
访问 Map 集合
hobbies3:singing
hobbies3:singing
hobbies3:singing
?? 编辑 Controller 代码
public class Person {
private String name;
private Integer age;
private String[] hobbies1;
private List hobbies2;
private Map hobbies3;
// 略写 setter 和 getter 方法
}
@Controller
public class ThymeleafController {
@GetMapping("/hello")
public String hello(Model model) {
Map hobbies = new HashMap<>();
hobbies.put("hobby1", "dancing");
Person person = new Person();
person.setName("Bob");
person.setHobbies1(new String[]{"dancing"});
person.setHobbies2(Arrays.asList("dancing"));
person.setHobbies3(hobbies);
model.addAttribute("person", person);
return "test";
}
}
?? 启动并访问
访问localhost:8080/hello
,网页显示:
? 使用内置对象
Thymeleaf 为变量所在域提供了一些内置对象,变量表达式${...}
可以直接使用:
-
#ctx
:上下文对象 -
#vars
:上下文变量 -
#locale
:上下文区域设置 -
#request
:HttpServletRequest 对象(仅限 Web Context) -
#response
:HttpServletResponse 对象(仅限 Web Context) -
#session
:HttpSession 对象(仅限 Web Context) -
#servletContext
:ServletContext 对象(仅限 Web Context)
具体使用代码如下:
Thymeleaf Test
default text
default text
@Controller
public class ThymeleafController {
@GetMapping("/hello")
public String hello(HttpServletRequest request, HttpSession session) {
request.setAttribute("requestObject", "读取 request 域内容");
session.setAttribute("sessionObject", "读取 session 域内容");
return "test";
}
}
访问localhost:8080/hello
,网页显示:
同时,Thymeleaf 还提供了一系列 Utility 工具对象(内置于 Context 中),${...}
可以直接访问:
-
#dates
:日期格式化内置对象,具体方法可以参照java.util.Date
-
#calendars
:类似于#dates
,但是是java.util.Calendar
类的方法 -
#numbers
:数字格式化 -
#strings
:字符串格式化,具体方法可以参照java.lang.String
,如 startsWith、contains等 -
#bools
:判断 boolean 类型的工具 -
#arrays
:数组操作的工具 -
#lists
:列表操作的工具,参照java.util.List
-
#sets
:Set操作工具,参照java.util.Set
-
#maps
:Map操作工具,参照java.util.Map
具体使用代码如下:
Thymeleaf Test
#dates 工具类测试
year :
month :
day :
hour :
minute :
second :
格式化:
yyyy-MM-dd HH:mm:ss 格式化:
#strings 工具类测试
testString初始值 :
toUpperCase :
toLowerCase :
equalsIgnoreCase :
indexOf :
substring :
startsWith :
contains :
#bools 工具类测试
#arrays 工具类测试
length :
contains :
containsAll :
循环读取 :
#lists 工具类测试
size :
contains :
sort :
循环读取 :
#maps 工具类测试
size :
containsKey :
containsValue :
读取map中键为id2的值 :
@Controller
public class ThymeleafController {
@GetMapping("/hello")
public String hello(Model model) {
model.addAttribute("testDate", new Date());
model.addAttribute("testString", "SpringBoot Thymeleaf 学习");
model.addAttribute("testBool", true);
model.addAttribute("testArray", new Integer[]{2018, 2019, 2020, 2021});
model.addAttribute("testList", Arrays.asList("Spring", "Spring Boot", "Thymeleaf", "MyBatis", "Java"));
MaptestMap = new HashMap<>();
testMap.put("id1", "Windows");
testMap.put("id2", "Linux");
testMap.put("id3", "Mac");
model.addAttribute("testMap", testMap);
return "test";
}
}
访问localhost:8080/hello
,网页显示:
#dates 工具类测试
year : 2020
month : 11
day : 8
hour : 17
minute : 28
second : 46
格式化: 2020年11月8日 CST 下午5:28:46
yyyy-MM-dd HH:mm:ss 格式化: 2020-11-08 17:28:46
#strings 工具类测试
testString初始值 : SpringBoot Thymeleaf 学习
toUpperCase : SPRINGBOOT THYMELEAF 学习
toLowerCase : springboot thymeleaf 学习
equalsIgnoreCase : false
indexOf : 2
substring : gBoo
startsWith : true
contains : true
#bools 工具类测试
true
#arrays 工具类测试
length : 4
contains : false
containsAll : true
循环读取 : 2018 2019 2020 2021
#lists 工具类测试
size : 5
contains : false
sort : [Java, MyBatis, Spring, Spring Boot, Thymeleaf]
循环读取 : Spring Spring Boot Thymeleaf MyBatis Java
#maps 工具类测试
size : 3
containsKey : true
containsValue : true
读取map中键为id2的值 : Linux
选择表达式*{}
选择表达式和变量表达式类似,不过它会用一个预先选择的对象来代替上下文变量容器来执行,被选择的对象使用th:object
标签来指定:
name:Alice
name:Alice
在不考虑上下文的情况下,${...}
和*{...}
两者没有区别,唯一区别在于使用*{...}
前可以在父标签中通过th:object
预先指定一个对象代替上下文变量容器:
...
...
...
链接表达式@{}
链接表达式@{...}
用于页面跳转或者资源的引入,一般用于替换 href 标签中的链接 URL 地址,例如:
Default URL
Default URL
Default URL
除此之外,链接表达式也可以读取变量值进行动态拼接 URL 地址:
Default URL
Default URL
Default URL
如果链接的 URL 地址用多个参数,可以自行拼接字符串,还是使用逗号隔开,写法如下:
Default URL
分段表达式~{}
分段表达式~{}
用于将标记片段移动到模板,一般使用th:insert
或th:replace
引用片段。
基本使用
? 标记片段
标记片段
? 引用片段
最终生成代码如下:
aaa
aaa
分段表达式传参
分段表达式~{}
可以传递参数,根据传递参数的不同显示不同的样式,例如:
条件逻辑判断
?? 条件表达式
Thymeleaf Test
当前的用户为:Admin
当前的用户为:Admin
当前的用户为:Admin
当前的用户为:Admin
@Controller
public class ThymeleafController {
@GetMapping("/hello")
public String hello() {
return "test";
}
}
访问localhost:8080/hello
,网页显示:
th:if 和 th:unless
Thymeleaf 使用th:if
和th:unless
进行条件判断,HTML5 标签中的内容只有th:if
的表达式条件为 true 时才显示,th:unless
与th:if
恰好相反,只有表达式条件为 false 时才显示 HTML5 标签中的内容。
Thymeleaf Test
th:if 条件判断
当前的用户为:Default Text.
th:unless 条件判断
当前的用户为:Default Text.
@Controller
public class ThymeleafController {
@GetMapping("/hello")
public String hello(Model model) {
Person person = new Person();
person.setName("Alice");
model.addAttribute("person", person);
return "test";
}
}
访问localhost:8080/hello
,网页显示:
-
如果表达式值为 null,直接返回 true;
-
如果表达式值不为 null,以下情况返回 true:
- 表达式值为 boolean 类型,并且为 true;
- 表达式值是数值类型,并且不为零;
- 表达式值是字符类型,并且不为零;
- 表达式值是 String 类型,并且不是 “false” “off” 或 “no”;
- 表达式值不是 boolean、数值、字符、String 类型的其他类型。
th:unless
的表达式判断规则和th:if
相反。
th:switch
Thymeleaf 支持多路选择 Switch 结构,类似于 Java 的swith...case...default
,只不过默认属性 default 用 * 表示,使用如下:
Thymeleaf Test
User is an administrator
User is an manager
User is some other thing
@Controller
public class ThymeleafController {
@GetMapping("/hello")
public String hello(Model model) {
model.addAttribute("role", "manager");
return "test";
}
}
访问localhost:8080/hello
,网页显示:
循环迭代访问
?? 基本迭代
Thymeleaf Test
姓名
年龄
public class Person {
private String name;
private Integer age;
public Person(String name, Integer age) {
this.name = name;
this.age = age;
}
// getter 和 setter 方法略写
}
@Controller
public class ThymeleafController {
@GetMapping("/hello")
public String hello(Model model) {
List persons = new ArrayList<>();
persons.add(new Person("张三", 10));
persons.add(new Person("李四", 20));
persons.add(new Person("王五", 30));
persons.add(new Person("赵六", 40));
model.addAttribute("persons", persons);
return "test";
}
}
访问localhost:8080/hello
,网页显示:
th:each
除了循环迭代元素基本使用外,还可以设置状态变量来跟踪迭代器的状态,状态变量有如下属性:
- index:当前迭代元素的索引,从 0 开始
- count:当前迭代元素的索引,从 1 开始
- size:当前迭代集合中元素的总数
- current:当前的迭代元素对象
- even/odd:布尔值,判断当前迭代元素的索引是否为偶/奇数(从1开始索引)
- first:布尔值,判断当前迭代元素是否为第一个
- last:布尔值,判断当前迭代元素是否为最后一个
Thymeleaf Test
index
count
姓名
年龄
@Controller
public class ThymeleafController {
@GetMapping("/hello")
public String hello(Model model) {
List persons = new ArrayList<>();
persons.add(new Person("张三", 10));
persons.add(new Person("李四", 20));
persons.add(new Person("王五", 30));
persons.add(new Person("赵六", 40));
model.addAttribute("persons", persons);
return "test";
}
}
访问localhost:8080/hello
,网页显示:
参考
- Thymeleaf 语法详解及编码实践
- Thymeleaf 内置工具