thymeleaf模板解析
(一)模板引擎概述
thymeleaf是一款用于渲染XML/XHTML/HTML5内容的模板引擎。类似JSP, Velocity,FreeMaker等,它也可以轻易的与Spring MVC等Web框架进行集成作为Web应用的模板引擎。与其它模板引擎相比,Thymeleaf最大的特点是能够
直接在浏览器中打开并正确显示模板页面,而不需要启动整个Web应用Spring Boot推荐使用Thymeleaf、Freemarker等现代的模板引擎技术;一但导入相
关依赖,会自动配置ThymeleafAutoConfiguration、FreeMarkerAutoConfiguration。
模板引擎工作原理图:
(二)SpringBoot使用thymeleaf 入门案例
1 构建maven工程引入技术依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.4.3</version>
</dependency>
2 在application.yml当中添加配置
spring:
#开始thymeleaf设置
thymeleaf:
#禁用模板缓存
cache: false
3 编写Controller文件
@Controller
@RequestMapping("/index")
public class IndexController {
@RequestMapping("/get")
public String getIndex(Model model){
model.addAttribute("msg","欢迎打开首页~~");
return "index";
}
}
4 编写模板文件
在resources/templates 下新建 index.html
通过 类似EL 表达式将 Model 中的数据填充到 h1 标签中
<!DOCTYPE html>
<!-- 引入命名空间 -->
<html lang="en" xmlns:th="http://www.thymeleaf.org" >
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- 把request域中的值传到页面h1标签中 -->
<h1 th:text="${msg}">----</h1>
</body>
</html>
5 运行访问地址 http://localhost:8080/index/get
Thymeleaf 语法简介
使用thymeleaf模板进行数据交互
1、修改标签文本
controller中方法
@RequestMapping("/text")
public String text(Model model){
model.addAttribute("msg","文本信息~~ ");
return "text";
}
html页面
- th:text 转义特殊字符
- th:utext 不转义特殊字符
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 th:text="${msg}"></h1>
<h1 th:utext="${msg}"></h1>
</body>
</html>
效果
2、打印对象属性
创建是个对象 User 生成get、set方法
public class User {
private Integer id;
private String name;
private int age;
}
controller层调用方法,模拟数据
图片在resources/resources/images/目录下
@RequestMapping("/bean")
public String bean(Model model){
// 把对象存入request域
User user = new User();
user.setId(1);
user.setName("张三");
user.setAge(23);
model.addAttribute("user",user);
// 利用Map集合 把图片存入request域
Map<String, Object> map = new HashMap<>();
map.put("pic","/images/mysql.jpg");
model.addAttribute("map",map);
return "user";
}
html页面信息
- th:src 修改指定属性默认值
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 th:text="${user.id}"></h1>
<h1 th:text="${user.name}"></h1>
<h1 th:text="${user.age}"></h1>
<!-- th:src 修改指定属性默认值 -->
<img th:src="${map.pic}" width="100" height="100">
</body>
</html>
效果
3、循环遍历集合
controller层调用方法,模拟数据
@RequestMapping("/list")
public String list(Model model){
ArrayList<Object> list = new ArrayList<>();
list.add(new User(1,"张三",23));
list.add(new User(2,"李四",24));
list.add(new User(3,"王五",25));
list.add(new User(4,"赵六",26));
list.add(new User(5,"周七",27));
model.addAttribute("list",list);
return "list";
}
html页面回显
- th:each 遍历
iterStat 称作状态变量,属性有:
index:当前迭代对象的 index(从 0 开始计算)
count:当前迭代对象的 index(从 1 开始计算)
size:被迭代对象的大小
current:当前迭代变量
even/odd:布尔值,当前循环是否是偶数/奇数(从 0 开始计算)
first:布尔值,当前循环是否是第一个
last:布尔值,当前循环是否是最后一个
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<table border="1">
<tr>
<td>序号</td>
<td>id</td>
<td>姓名</td>
<td>年龄</td>
</tr>
<!-- user-回显集合中的元素 iterStat-称作状态变量 ${list}--取出的集合 -->
<tr th:each="user,iterStat :${list}">
<td th:text="${iterStat.count}">序号</td>
<td th:text="${user.id}">id</td>
<td th:text="${user.name}">姓名</td>
<td th:text="${user.age}">年龄</td>
</tr>
</table>
</body>
</html>
效果
4、字符串的拼接以及超链接
controller层调用方法
@RequestMapping("/demo")
public String demo(Model model){
model.addAttribute("user","用户1");
model.addAttribute("href","https://www.baidu.com/");
model.addAttribute("username","百度");
return "demo";
}
html页面
- th:href
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- 超链接 -->
<a th:href="${href}" th:text="${username}"></a>
<!-- 字符串拼接 -->
<h1 th:text="'欢迎:'+${user}+' 登录成功'"></h1>
<h1 th:text="|欢迎:${user}登录成功|"></h1>
</body>
</html>
效果
5、条件判断、选择语句
controller方法
@RequestMapping("/judge")
public String judge(Model model){
model.addAttribute("flag","yes");
model.addAttribute("admin","zhangsan");
model.addAttribute("username","lisi");
return "judge";
}
html页面
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- th:if 条件成立时 显示 -->
<h1 th:if="${flag=='yes'}">th:if 条件成立时 显示 </h1>
<!-- th:unless 条件成立时 显示 -->
<h1 th:unless="${flag=='no'}">th:unless 条件成立时 显示</h1>
<!-- switch 选择语句 -->
<div th:switch="${admin}">
<p th:case="'zhangsan'">显示1</p>
<p th:case="${username}">显示2</p>
</div>
</body>
</html>
效果
6、片段fragment定义使用
controller方法
@RequestMapping("/fragment")
public String fragment(Model model){
return "fragment";
}
html页面
- tags.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 th:fragment="top">头部信息</h1>
<h1 th:fragment="tig">身体信息</h1>
<h1 th:fragment="footer">尾部信息</h1>
</body>
</html>
- fragment.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- th:insert 把片段的内容 插入到当前的位置 -->
<div style="color: #82ff6c" th:insert="~{tags :: top}"></div><br>
<!-- th:replace 把片段的内容(附带标签) 替换到当前的标签 -->
<div style="color: #82ff6c" th:replace="~{tags :: tig}"></div><br>
<!-- th:include 保留自己的主标签 不要片段中的标签,直接把内容拿过来 -->
<div style="color: #82ff6c" th:include="~{tags :: footer}"></div><br>
</body>
</html>
效果
- 页面源代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- th:insert 把片段的内容 插入到当前的位置 -->
<div style="color: #82ff6c"><h1>头部信息</h1></div><br>
<!-- th:replace 把片段的内容 替换到当前的标签 -->
<h1>身体信息</h1><br>
<!-- th:include 保留自己的主标签 不要片段中的标签,直接把内容拿过来 -->
<div style="color: #82ff6c">尾部信息</div><br>
</body>
</html>
7、表达式内置对象使用
- #dates 与java.util.Date对象的方法对应,格式化、日期组件抽取等等
- #numbers 格式化数字对象的工具方法
- #strings 与java.lang.String对应的工具方法
controller方法
@RequestMapping("/neibean")
public String neibean(Model model){
//日期时间
Date date = new Date();
model.addAttribute("date", date);
//小数的金额
double price=128.5678D;
model.addAttribute("price", price);
//定义大文本数据
String str="Thymeleaf是Web和独立环境的现代服务器端Java模板引擎,能够处理HTML,XML,JavaScript,CSS甚至纯文本。\r\n" +
"Thymeleaf的主要目标是提供一种优雅和高度可维护的创建模板的方式。为了实现这一点,它建立在自然模板的概念上,将其逻辑注入到模板文件中,不会影响模板被用作设计原型。这改善了设计的沟通,弥补了设计和开发团队之间的差距。\r\n" +
"Thymeleaf也从一开始就设计了Web标准 - 特别是HTML5 - 允许您创建完全验证的模板,如果这是您需要的\r\n" ;
model.addAttribute("strText", str);
//定义字符串
String str2="JAVA-offcn";
model.addAttribute("str2", str2);
return "neibean";
}
html页面
- 格式化日期: #dates.format(日期名称(request域中),格式化的格式)
- 格式化数字: #numbers.formatDecimal(数字名称(request域中),整数最少多少位,小数保留多少位)
- 格式化字符串:#strings.abbreviate(字符串名称(request域中),最首位开始展示多少位)
- 截取字符串 指定长度 :#strings.substring(字符串名称,起始位,截至位)
- 判断字符串是否为空 :#strings.isEmpty(字符串名称)
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- 格式化日期: #dates.format(日期名称(request域中),格式化的格式) -->
时间:<span th:text="${#dates.format(date,'yyyy-MM-dd,HH-mm-ss')}"></span> <br>
<!-- 格式化数字: #numbers.formatDecimal(数字名称(request域中),整数最少多少位,小数保留多少位) -->
金额:<span th:text="${#numbers.formatDecimal(price,1,2)}"></span> <br>
<!-- 格式化字符串:#strings.abbreviate(字符串名称(request域中),最首位开始展示多少位) -->
介绍:<span th:text="${#strings.abbreviate(strText,40)}"></span> <br>
<!-- 判断字符串是否为空 :#strings.isEmpty(字符串名称) -->
<span th:if="${!#strings.isEmpty(str2)}">字符串str2不为空</span> <br>
<!-- 截取字符串 指定长度 :#strings.substring(字符串名称,起始位,截至位)-->
<span th:text="${#strings.substring(str2,0,4)}">字符串str2的值</span>
</body>
</html>
效果
8、定义方法
<dd th:each="value:${spec.attributeValue}">
<a href="javascript:;"
th:v-bind:class="|{selected:isSelected('${spec.attributeName}','${value}')}|"
th:@click="|clickSpecValue('${spec.attributeName}','${value}')|"
th:text="${value}"
>
</a>
</dd>
<script th:inline="javascript">
var item = new Vue({
el: '#app',
data: {
// 将itemList模板数据 转为 vue对象
skuList: [[${
itemList}]],
sku: {
}, // 当前页面展示的 sku数据 (title 和 price)
spec: {
} // 当前用户选择的规格
},
// 页面初始化调用的方法
created: function(){
// 当前页面渲染完成之后,将 itemList 中的第一个元素作为默认展示的元素
this.sku = this.skuList[0];
//console.log(typeof this.skuList[0].spec);
this.spec = JSON.parse(this.skuList[0].spec);
},
methods: {
isSelected: function(specName,specValue){
if(this.spec[specName] == specValue){
return true;
}else{
return false;
}
},
clickSpecValue: function(specName,specValue){
// 记录当前用户选择的规格和规格选项
this.$set(this.spec,specName,specValue);
// 需要skuList中的每个item对象的spec属性和 this.spec 匹配
for(var i = 0; i < this.skuList.length; i++){
if(this.equalsObj(this.spec,JSON.parse(this.skuList[i].spec))){
this.sku = this.skuList[i];
}
}
},
equalsObj: function(obj1,obj2){
// 遍历obj1中的属性
for(var pro in obj1){
if(obj1[pro] != obj2[pro]){
return false;
}
}
return true;
}
}
})
</script>