官网: https://www.thymeleaf.org/documentation.html
1. 什么是 Thymeleaf
- Thymeleaf是⾯向Web和独⽴环境的现代服务器端Java模板引擎,能够处 理HTML,XML,JavaScript,CSS甚⾄纯⽂本。
- Thymeleaf旨在提供⼀个优雅的、⾼度可维护的创建模板的⽅式。 为了实 现这⼀⽬标,Thymeleaf建⽴在⾃然模板的概念上,将其逻辑注⼊到模板 ⽂件中,不会影响模板设计原型。 这改善了设计的沟通,弥合了设计和 开发团队之间的差距。
- Thymeleaf从设计之初就遵循Web标准——特别是HTML5标准 ,如果需 要,Thymeleaf允许您创建完全符合HTML5验证标准的模板。
-
Tips:
Spring Boot 体系内推荐使用Thymeleaf作为前端页面模板,并且Spring Boot 2.0 中默认使用 Thymeleaf 3.0,性能提升幅度很大。
2. Thymeleaf的特点
- Thymeleaf在不管是否连接服务器的环境下皆可运行,即它可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。
- Thymeleaf开箱即用的特性。它支持标准方言和Spring 方言,可以直接套用模板实现JSTL、OGNL表达式效果,避免每天套模板、改JSTL、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言。
- Thymeleaf提供Spring标准方言和一个与SpringMVC完美集成的可选模块,可以快速地实现表单绑定、属性编辑器、国际化等功能
-
Thymeleaf相关知识脑图
Thymeleaf相关知识脑图
3. Thymeleaf的快速入门 (简单例子)
- 新建一个Springboot项目,加上Thymeleaf的starter
pom.xml (仅展示重要依赖)
- 新建一个Springboot项目,加上Thymeleaf的starter
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
- 配置properties文件,加上不开启Thymeleaf的缓存
spring.thymeleaf.cache=false
- 创建hello.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>欢迎使用Thymeleaf模板</p>
<p th:text="${msg}">这是静态段落文字</p>
</body>
</html>
- 创建HelloController
package cn.lazyfennec.springbootthymeleaf.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @Author: Neco
* @Description:
* @Date: create in 2022/5/4 16:20
*/
@Controller
public class HelloController {
@RequestMapping("/hello")
public String hello(ModelMap map) {
map.addAttribute("msg", "Hello Neco!!!");
return "hello";
}
}
- 运行并访问 http://localhost:8080/hello 进行测试
测试结果
- 运行并访问 http://localhost:8080/hello 进行测试
4. Thymeleaf 的基本语法 - th属性
- 文本属性
- 文本拼接:||
- 文本信息:th:text,th:id,th:value...
- 文本信息(可以解析HTML各位): th:utext
@RequestMapping("/hello") public String hello(ModelMap map){ map.addAttribute("message","你好<b>这里加粗了</b>"); map.put("id","这是id"); map.put("value","这是value"); map.put("utext","这是utext里面的内容<b>这里加粗了</b>"); return "hello"; }
<body> <!--文本属性-字符串的拼接:写法1--> <p th:text="|welcome to shanghai,${message}|"></p> <!--文本属性-字符串的拼接:写法2--> <p th:utext="'welcome to shanghai,'+${message}"></p> <!--文本属性-id属性--> <p th:id="${id}"></p> <!--文本属性-value属性--> <input th:value="${value}"/> <!--使用内联标签来书写--> <!--不带html的解析,类似于th:text--> <p>[[|welcome to shanghai,${message}|]]</p> <!--带html的解析,类似于th:utext--> <p>[('welcome to shanghai,'+${message})]</p> <!--也可以直接写文本--> <p>[['welcome to shanghai']]</p> </body>
- 条件属性
- if判断:
th:if
- unless判断:
th:unless
- switch判断:
th:switch...th:case
@RequestMapping("/if") public String hello(ModelMap map){ map.put("flag","yes"); map.put("baidu","http://www.baidu.com"); map.put("taobao","http://www.taobao.com"); map.put("age",19); return "if"; }
<body> <!--if:如果条件成立,就展示--> <!--th:href:允许在href属性里面使用thymeleaf语法,超链接需要用@{}开头,里面可以写model里面的key--> <a th:if="${flag eq 'yes'}" th:href="@{${baidu}}">baidu1</a><br> <!--th:href:专门用来使用URL地址的,既可以直接像上面那样在里面直接写${}, 也可以先定义个变量用大括号括起来然后在url的最后面使用一个小括号来对该变量进行赋值--> <a th:if="${flag eq 'yes'}" th:href="@{{baidusite}(baidusite=${baidu})}">baidu2</a><br> <!--直接在href里面写${}是无法获取到后台model里面的数据的--> <a th:if="${flag eq 'yes'}" href="${baidu}">baidu3</a><br> <!--不使用th:href的话,href里面只能写死的数据--> <a th:if="${flag eq 'no'}" href="http://www.baidu.com">baidu4</a><br> <!--unless:如果条件不成立,就展示--> <a th:unless="${flag eq 'no'}" th:href="@{http://www.taobao.com}">taobao</a> <!--使用switch--> <div th:switch="${age}"> <p th:case="18">这是张三</p> <p th:case="19">这是李四</p> <p th:case="20">这是王五</p> <p th:case="*">这是谁我不认识</p> </div> </body>
- 循环属性-th:each
- th:each迭代list
- th:each的内置属性
- th:each迭代map
@RequestMapping("/list") public String list(ModelMap map){ List<User> list = getUserList(); map.addAttribute("list",list); return "list"; }
<table> <tr> <th>姓名</th> <th>年龄</th> <th>密码</th> </tr> <tr th:each="user:${list}"> <td th:text="${user.name}"></td> <td th:text="${user.age}"></td> <td th:text="${user.pass}"></td> </tr> </table>
5. Thymeleaf的表达式语法
-
${...}
变量表达式:也叫OGNL表达式或Spring EL表达式,用于调用各种属性和方法
- a) 可以获取对象的属性和方法
- b) 可以使用ctx, vars, locale, request, response, session, servletContext内置对象
- c) 可以使用dates, numbers, strings, objects, arrays, lists, sets, maps等内置方法
-
@{...}
链接表达式:不管是静态资源的引用,form表单的请求,凡是链接都可以用@{...]
- a) 无参:@{/xxx}
- b) 有参:@{/xxx(k1=v1,k2=v2)},对应url结构:xxx?k1=v1&k2=v2
- c) 引入本地资源:@{/项目本地的资源路径}
- d) 引入外部资源:@{/webjars/资源在jar包中的路径}
-
#{...}
消息表达式:用于从消息源中提取消息内容实现国际化
- 语法和变量表达式相比多了个获取参数的方式
- 消息源主要是properties文件
-
~{...}
代码块表达式:把某一段定义好的代码块插入到另一个页面中,一般用于定义出一套通用的header或者是footer
- 语法:
~[templatename:fragmentname}
或者~[templatename:.id}
,如果省略templatename,它将在当前页面进行寻找指定的代码块,注意:~可以省略
a) templatename:模版名,定义模板的写法:<footer th:fragment="copy">
b) fragmentname:片段名,引入模板的写法: <div th:insert="comm/foot : copy">
c) id: HTML的id选择器,使用时要在前面加上#号,不支持class选择器- 代码块表达式需要配合th属性(th:insert,th:replace,th:include)一起使用。
a) th:insert:将代码块片段整个插入到使用了th:insert的HTML标签中
b) th:replace:将代码块片段整个替换使用了th:replace的HTML标签中
c) th:include:将代码块片段包含的内容插入到使用了th:include的HTML标签中
-
*{...}
选择变量表达式:是另一种类似${...}
,在某些时候,两者是等价的,选择变量表达式在执行时是在选择的对象上求解(使用th:object来选择对象),而${...}
是在上下文的变量Map上求解。
- 两者获取对象里边属性的方法
- 两者进行混用的条件
6. Thymeleaf中表达式支持的语法
- 字面
- 文本文字: 'one text','Another one!',...
- 数字文字:0,34,3.0,12.3,...
- 布尔文字: true,false
- 空字面: null
- 文字操作:
- 字符串连接:+
- 文字替代:|The name is ${name}
- 算术运算:
- 运算符: +,-,*,/,%
- 布尔运算:
- 二元运算符:and,or
- 布尔否定(一元运算符)∶ !, not
- 比较和相等
- 比较:>, <,>=,<= (gt,lt,ge,le)
- 相等判断:==,!= (eq,ne)
- 条件运算符
- lF-THEN:(if) ? (then)
- lF-THEN-ELSE: (if) ? (then) : (else)
- 默认: (value) ?: (defaultvalue)
7. Thymeleaf中的基础对象
- #ctx:上下文对象
- #vars:上下文对象(和#ctx相同,但是一般用#ctx)
- #locale:区域对象
- #request:(仅Web环境可用)HttpServletRequest对象
- #response:(仅 Web环境可用)HttpServletResponse对象
- #session:(仅Web环境可用)HttpSession对象
- #servletContext:(仅Web环境可用)ServletContext 对象
- param:获取请求的参数
- session:访问session属性
- application:获取应用程序/ servlet上下文属性
注意:以上三个不带#的对象,都拥有以下方法:size(),isEmpty(),containsKey(), .key
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>if,unless</title>
</head>
<body>
<h1>ctx上下文对象</h1>
<p th:text="${#ctx}"></p>
<h1>ctx获取保存在map里的数据</h1>
<p th:text="${#ctx.getVariable('a')}"></p>
<h1>vars上下文变量</h1>
<p th:text="${#ctx}"></p>
<h1>locale区域对象</h1>
<p th:text="${#locale}"></p>
<p th:text="${#locale.country}"></p>
<h1>param的使用</h1>
<!-- http://127.0.0.1:8088/baseObject?a=1&b=2&c=3,
param代表获取到请求里的参数-->
<p th:text="|size:${param.size()},a:${param.a}|"></p>
<h1>来获取session里面的对象</h1>
<p th:text="${#session.getAttribute('session')}"></p>
<p th:text="${session.session}"></p>
</body>
</html>
package com.study.thymeleaf.thymeleafdemo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
/**
* @Author 来苏
* 测试基础对象
* #ctx、#vars、#locale
*/
@Controller
public class BaseObjectController {
@RequestMapping("/baseObject")
public String map1(ModelMap map, HttpServletRequest request, HttpSession session) {
map.put("a", 123);
map.put("b", "bbb");
request.setAttribute("request", "123");
session.setAttribute("session", "321");
return "base";
}
}
8. Thymeleaf的常用工具类
- #strings:字符串工具类
- #lists: List工具类
- #arrays:数组工具类
- #sets: Set工具类
- #maps:常用Map方法。
- #objects:一般对象类,通常用来判断非空
- #bools:常用的布尔方法。
- #execInfo:获取页面模板的处理信息。
- #messages:在变量表达式中获取外部消息的方法,与使用
#{...}
语法获取的方法相同。 - #uris:转义部分URL/URI的方法。
- #conversions:用于执行已配置的转换服务的方法。
- #dates:时间操作和时间格式化等。
- #calendars:用于更复杂时间的格式化。
- #numbers:格式化数字对象的方法。
- #aggregates:在数组或集合上创建聚合的方法。
- #ids:处理可能重复的id属性的方法。
9. body内的内联
- 例子
<!--内联标签的使用-->
<!--内联写法1-->
<p >[[|welcome to china,${text}|]]</p>
<!--内联写法2-->
<p>[('welcome to china,'+${text})]</p>
<!--内联写法3-->
<p>[('welcome to china')]</p>
-
我们的习惯
1.有时候这样更合适:<p>Hello,[[${session.user.name}]]</p>
2.而不喜欢这样写代码:<p>Hello, <span th:text="${session.user.name]">Sebastian</span></p>
-
th属性和内联标签的对应关系
1.[[...]]
等价于th:text
(结果将被HTML转义)
2.[(...)]
等价于th:utext
(结果不会执行HTML转义)。 -
body上加上inline="none" 可以使内联失效
<body th:inline="none">
10. JS里的内联
- 例子
<script th:inline="javascript">
var name = [[${name}]];
var userName = [[${user.name}]];
var userAge = [[${user.age}]];
var userPass = [[${user.pass}]];
alert("name:"+name+",userName:"+userName+",userAge:"
+userAge+",userPass:"+userPass);
</script>
-
在JavaScript中使用内联标签(默认不支持)︰
1.在script标签上引入对内联的支持:<script type="text/javascript" th:inline="javascript">
2.在script标签里书写[[]]、[()]来获取后端数据; -
在JavaScript中实现前后端分离(也称之为JavaScript自然模板)∶
1.Thymeleaf的目标就是希望前后端分离,即同一个Html文件前端人员以静态原型的方式打开时,看到的是它们的内容,而后端人员通过服务器打开时,看到的是动态的数据;
2.直接在数据上使用js注释即可实现前后端分离:var msg =/*[[S{name]]*/'666666'
3.当在服务器打开该页面时,就会展示${name}
的值,当时在静态打开时,就展示666666
-
在JavaScript中自动进行对象序列化
1.JavaScript 内联的一个重要的特性是,内联表达式的计算结果不限于字符串,它能自动的将后台的数据序列化为javascript对象 -
Tips
js中开启内联标签模式只能是在Html文件内部的JavaScript 代码,不能在引入的外部JavaScript文件中进行操作
11. css里的内联
- 例子
<style type="text/css" th:inline="css" th:with="color='yellow',
fontSize='25px'">
p{
/*这里是一个注释*/
color: /*[[${color}]]*/ red;
/*fontSize需要使用[()]来忽略HTML的转义*/
font-size:[(${fontSize})];
}
</style>
-
在CSS中使用内联标签(默认不支持)∶
1.在style标签上引入对内联的支持:<style th:inline="css">
2.在style标签里书写[[]]
、[()]
来获取后端数据; -
在CSS中实现前后端分离(也称之为CSS自然模板)∶
1.与内联JavaScript一样,CSS内联也允许<style>标签可以静态和动态地工作,即通过在注释中包含内联表达式作为CSS自然模板。
2.当服务器动态打开时,字体颜色为黄色;当以原型静态打开时,显示的是红色,因为Thymeleaf会自动忽略掉css注释之后和分号之前的代码。
3.在CSS中,因为CSS自然模板的问题,所以不能在css中像以前一样添加注释,因为Thymeleaf会将它们当做模板进行处理。 -
Tips
与内联JavaScript一样,内联CSS同样只能Html内嵌的<style >标签中进行使用,不能在外部关联的CSS文件中进行使用
如果觉得有收获就点个赞吧,更多知识,请点击关注查看我的主页信息哦~
网友评论