1 thymeleaf简介
1.1 什么是thymeleaf
Thymeleaf是适用于Web和独立环境的现代服务器端Java模板引擎,能够处理HTML,XML,JavaScript,CSS甚至纯文本。
Thymeleaf的主要目标是提供一种优雅且高度可维护的模板创建方法。为此,它以自然模板的概念为基础,以不影响模板用作设计原型的方式将其逻辑注入模板文件。这样可以改善设计沟通,并缩小设计团队与开发团队之间的差距。
1.2 thymeleaf可以处理那些模板
开箱即用的Thymeleaf可以处理六种模板,每种模板都称为模板模式:
- HTML模板
- XML格式
- 文本格式
- JAVASCRIPT格式
- CSS格式
- 原生的文本
1.3 特点
- 动静结合:Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。这是由于它支持 html 原型,然后在 html 标签里增加额外的属性来达到模板+数据的展示方式。浏览器解释 html 时会忽略未定义的标签属性,所以 thymeleaf 的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静态内容,使页面动态显示。
- 开箱即用:它提供标准和spring标准两种方言,可以直接套用模板实现JSTL、 OGNL表达式效果,避免每天套模板、该jstl、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言。
- 多方言支持:Thymeleaf 提供spring标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的实现表单绑定、属性编辑器、国际化等功能。
- 与SpringBoot完美整合,SpringBoot提供了Thymeleaf的默认配置,并且为Thymeleaf设置了视图解析器,我们可以像以前操作jsp一样来操作Thymeleaf。代码几乎没有任何区别,就是在模板语法上有区别。
2 环境准备
2.1 创建一个springboot项目
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-72T48hCn-1620116100586)(C:\Users\99226\Desktop\img\1620031015924.png)]](https://img-blog.csdnimg.cn/20210504161523452.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ2MzI5Nzgw,size_16,color_FFFFFF,t_70)
2.2 导入相关依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.thymeleaf</groupId>
<artifactId>stydy-thymeleaf</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<!--继承父工程 spring boot-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<relativePath/>
</parent>
<!--项目编码方式-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<!--导入相关依赖-->
<dependencies>
<!--thymeleaf起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--springMVC起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--spring测试类起步依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--lombok 代码模板-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
2.3 快速起步
1 创建启动器
/**
* 启动器
* @Author: CodeBull
* @Date: 2021/5/3
* @version: 1.0
*/
@SpringBootApplication
public class ThymeleafApplication {
public static void main(String[] args) {
SpringApplication.run(ThymeleafApplication.class, args);
}
}
2 创建controller
/**
* 欢迎页面控制器
*
* @Author: CodeBull
* @Date: 2021/5/3
* @version: 1.0
*/
@Controller
public class WelcomeController {
@Autowired
private WelcomeService welcomeService;
/**
* 响应欢迎页面
* @param model 响应数据
* @return welcome欢迎页面
*/
@GetMapping("/welcome")
public String welcome(Model model) {
model.addAttribute("welcome", welcomeService.welcome());
return "welcome";
}
}
3 创建service层
创建相关接口及其实现类
/**
* 逻辑层接口
*
* @Author: CodeBull
* @Date: 2021/5/3
* @version: 1.0
*/
public interface WelcomeService {
/**
* 欢迎页面相关逻辑
* @return 欢迎语
*/
public String welcome();
}
/**
* 欢迎页面逻辑层实现
*
* @Author: CodeBull
* @Date: 2021/5/3
* @version: 1.0
*/
@Service
public class WelcomeServiceImpl implements WelcomeService {
@Override
public String welcome() {
return "Hello,Thymeleaf!";
}
}
4 创建相关视图
在resources/templates目录下创建,且讲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>
</head>
<body>
<h1 th:text="${welcome}">默认数据</h1>
</body>
</html>
5 效果
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5UyHxSxH-1620116100588)(C:\Users\99226\Desktop\img\1620032921374.png)]](https://img-blog.csdnimg.cn/20210504161609203.png)
6 解释
启动器中的默认设置:
- 默认前缀:classpath:/templates/
- 默认后缀:.html
3 数据类型
3.1 基本数据类型
controller:
/**
* 测试基本数据类型
* @param modelMap 数据流转
* @return 基本数据类型测试页
*/
@GetMapping("/testComType")
public String testComType(ModelMap modelMap) {
modelMap.addAttribute("title", "基本数据类型测试");
//整型
modelMap.addAttribute("int", 100);
//浮点型
modelMap.addAttribute("double", 3.14);
//字符型
modelMap.addAttribute("string", "测试数据");
//布尔型
modelMap.addAttribute("boolean", false);
return "testComType";
}
html:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>欢迎页面</title>
</head>
<body>
<h1 th:text="${title}">默认数据</h1>
<h3>整型:</h3>
<h4 th:text="${int}"></h4>
<h3>浮点型:</h3>
<h4 th:text="${double}"></h4>
<h3>字符型:</h3>
<h4 th:text="${string}"></h4>
<h3>布尔型:</h3>
<h4 th:text="${boolean}"></h4>
</body>
</html>
效果:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tSb6PfWf-1620116100588)(C:\Users\99226\Desktop\img\1620053414089.png)]](https://img-blog.csdnimg.cn/20210504161624399.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ2MzI5Nzgw,size_16,color_FFFFFF,t_70)
3.2 集合数据类型
controller:
/**
* 测试集合数据类型
* @param modelMap 数据流转
* @return 集合数据类型测试页
*/
@GetMapping("/testCollectionType")
public String testCollectionType(ModelMap modelMap) {
modelMap.addAttribute("title", "集合数据类型测试");
//list集合测试
ArrayList<Integer> list = new ArrayList<>();
list.add(100);
list.add(200);
list.add(300);
modelMap.addAttribute("list", list);
//map集合测试
HashMap<String, String> map = new HashMap<>();
map.put("one", "测试元素一");
map.put("two", "测试元素二");
map.put("three", "测试元素三");
modelMap.addAttribute("map", map);
return "testCollectionType";
}
html:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>欢迎页面</title>
</head>
<body>
<h1 th:text="${title}">默认数据</h1>
<h3>list集合测试</h3>
<table>
<tr>
<th>序号</th><th>元素</th>
</tr>
<tr>
<td>1</td><td th:text="${list[0]}">暂无数据</td>
</tr>
<tr>
<td>2</td><td th:text="${list[1]}">暂无数据</td>
</tr>
<tr>
<td>3</td><td th:text="${list[2]}">暂无数据</td>
</tr>
</table>
<h3>map集合测试</h3>
<table>
<tr>
<th>key</th><th>value</th>
</tr>
<tr>
<td>one</td><td th:text="${map['one']}"></td>
</tr>
<tr>
<td>two</td><td th:text="${map['two']}"></td>
</tr>
<tr>
<td>three</td><td th:text="${map['three']}"></td>
</tr>
</table>
</body>
</html>
效果:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mysvu34b-1620116100591)(C:\Users\99226\Desktop\img\1620054902242.png)]](https://img-blog.csdnimg.cn/2021050416163579.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ2MzI5Nzgw,size_16,color_FFFFFF,t_70)
3.3 JavaBean数据类型
controller:
/**
* 测试JavaBean类型数据
* @param modelMap 数据流转
* @return JavaBean数据类型测试页
*/
@GetMapping("testBeanType")
public String testBeanType(ModelMap modelMap) {
modelMap.addAttribute("title", "JavaBean数据类型测试");
Student student = new Student(1, "张三", 18);
modelMap.addAttribute("student", student);
return "testBeanType";
}
html:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>欢迎页面</title>
</head>
<body>
<h1 th:text="${title}">默认数据</h1>
<h3>list集合测试</h3>
<table>
<tr>
<th>学号</th><th>姓名</th><th>年龄</th>
</tr>
<tr>
<td th:text="${student.getId()}">暂无数据</td>
<td th:text="${student.getName()}">暂无数据</td>
<td th:text="${student.getAge()}">暂无数据</td>
</tr>
<td th:text="${student.id}">暂无数据</td>
<td th:text="${student.name}">暂无数据</td>
<td th:text="${student.age}">暂无数据</td>
</tr>
</table>
</body>
</html>
效果:
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ATxkLjBG-1620116100593)(C:\Users\99226\Desktop\img\1620112871682.png)]](https://img-blog.csdnimg.cn/20210504161646428.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQ2MzI5Nzgw,size_16,color_FFFFFF,t_70)
3.4 自定义变量
当数据量比较多的时候,频繁的写student.就会非常麻烦。
因此,Thymeleaf提供了自定义变量来解决:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>欢迎页面</title>
</head>
<body>
<h1 th:text="${title}">默认数据</h1>
<h3>list集合测试</h3>
<table>
<tr>
<th>学号</th><th>姓名</th><th>年龄</th>
</tr>
<tr th:object="${student}">
<td th:text="*{id}">暂无数据</td>
<td th:text="*{name}">暂无数据</td>
<td th:text="*{age}">暂无数据</td>
</tr>
</table>
</body>
</html>
4 方法
ognl表达式本身就支持方法调用,例如:
<h2 th:object="${student}">
<p>FirstName: <span th:text="*{name.split(' ')[0]}">Jack</span>.</p>
<p>LastName: <span th:text="*{name.split(' ')[1]}">Li</span>.</p>
</h2>
4.1 环境相关对象
对象 |
作用 |
#ctx |
获取Thymeleaf自己的Context对象 |
#requset |
如果是web程序,可以获取HttpServletRequest对象 |
#response |
如果是web程序,可以获取HttpServletReponse对象 |
#session |
如果是web程序,可以获取HttpSession对象 |
#servletContext |
如果是web程序,可以获取HttpServletContext对象 |
4.2 全局对象
对象 |
作用 |
#dates |
处理java.util.date的工具对象 |
#calendars |
处理java.util.calendar的工具对象 |
#numbers |
用来对数字格式化的方法 |
#strings |
用来处理字符串的方法 |
#bools |
用来判断布尔值的方法 |
#arrays |
用来处理数组的方法 |
#lists |
用来处理List集合的方法 |
#sets |
用来处理set集合的方法 |
#maps |
用来处理map集合的方法 |
4.3 字面量
有的时候,我们需要在指令中填写基本类型如:字符串、数值、布尔等,并不希望被Thymeleaf解析为变量,这个时候称为字面值。
4.3.1 字符串字面值
使用一对单引号引用的内容就是字符串字面值了:
<p>
你正在观看 <span th:text="'thymeleaf'">template</span> 的字符串常量值.
</p>
4.3.2 数字字面量
数字不需要任何特殊语法,而且可以直接进行算术运算:
<p>今年是 <span th:text="2021">1970</span>.</p>
<p>两年后将会是 <span th:text="2021 + 2">1972</span>.</p>
4.3.3 布尔字面值
布尔类型的字面值是true或false:
<div th:if="true"> <!--这里引用了一个th:if指令,跟vue中的v-if类似,判断-->
你填的是true
</div>
4.4 拼接
普通字符串与表达式拼接的情况:
<span th:text="'欢迎您:' + ${user.name} + '!'"></span>
字符串字面值需要用''
,拼接起来非常麻烦,Thymeleaf对此进行了简化,使用一对|
即可:
<span th:text="|欢迎您:${user.name}|"></span>
与上面是完全等效的,这样就省去了字符串字面值的书写。
5 运算
需要注意:${}
内部的是通过OGNL表达式引擎解析的,外部的才是通过Thymeleaf的引擎解析,因此运算符尽量放在${}
外进行。
5.1 算术运算
支持的算术运算符:+ - * / %
<span th:text="${user.age}"></span>
<span th:text="${user.age}%2 == 0"></span>
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gOCXADk4-1620116100594)(file:///D:/为知笔记笔记存储/temp/7f6d4cf3-d40f-434b-a95e-17b351d36980/128/index_files/1526959990356.png)]](https://img-blog.csdnimg.cn/20210504161710211.png)
5.2 比较运算
支持的比较运算:>
, <
, >=
and <=
,但是>
, <
不能直接使用,因为xml会解析为标签,要使用别名。
注意 ==
and !=
不仅可以比较数值,类似于equals的功能。
可以使用的别名:gt (>), lt (<), ge (>=), le (<=), not (!). Also eq (==), neq/ne (!=).
5.3 条件运算
三元运算
<span th:text="${user.sex} ? '男':'女'"></span>
三元运算符的三个部分:conditon ? then : else
-
condition:条件
-
then:条件成立的结果
-
else:不成立的结果
5.4 默认值
有的时候,我们取一个值可能为空,这个时候需要做非空判断,可以使用 表达式 ?: 默认值
简写:
<span th:text="${user.name} ?: '二狗'"></span>
当前面的表达式值为null时,就会使用后面的默认值。
注意:?:
之间没有空格。
6 逻辑判断
6.1 if-else
有了if和else
,我们能实现一切功能_。
Thymeleaf中使用th:if
或者 th:unless
,两者的意思恰好相反。
<span th:if="${user.age} < 24">小鲜肉</span>
如果表达式的值为true,则标签会渲染到页面,否则不进行渲染。
以下情况被认定为true:
- 表达式值为true
- 表达式值为非0数值
- 表达式值为非0字符
- 表达式值为字符串,但不是
"false"
,"no"
,"off"
- 表达式不是布尔、字符串、数字、字符中的任何一种
其它情况包括null都被认定为false
6.2 分支判断
这里要使用两个指令:th:switch
和 th:case
<div th:switch="${user.role}">
<p th:case="'admin'">管理员</p>
<p th:case="'manager'">经理</p>
<p th:case="*">其他角色</p>
</div>
需要注意的是,一旦有一个th:case成立,其它的则不再判断。与java中的switch是一样的。
另外th:case="*"
表示默认,放最后。
7 循环
循环也是非常频繁使用的需求,我们使用th:each
指令来完成:
假如有用户的集合:users在Context中。
<tr th:each="user : ${users}">
<td th:text="${user.name}">Onions</td>
<td th:text="${user.age}">2.41</td>
</tr>
- ${users} 是要遍历的集合,可以是以下类型:
- Iterable,实现了Iterable接口的类
- Enumeration,枚举
- Interator,迭代器
- Map,遍历得到的是Map.Entry
- Array,数组及其它一切符合数组结果的对象
在迭代的同时,我们也可以获取迭代的状态对象:
<tr th:each="user,stat : ${users}">
<td th:text="${user.name}">Onions</td>
<td th:text="${user.age}">2.41</td>
</tr>
stat对象包含以下属性:
- index,从0开始的角标
- count,元素的个数,从1开始
- size,总元素个数
- current,当前遍历到的元素
- even/odd,返回是否为奇偶,boolean值
- first/last,返回是否为第一或最后,boolean值