Thymeleaf快速入门
Thymeleaf 是新一代 Java 模板引擎,与 Velocity、FreeMarker 等传统 Java 模板引擎不同,Thymeleaf 支持 HTML 原型,其文件后缀为“.html”,因此它可以直接被浏览器打开,此时浏览器会忽略未定义的 Thymeleaf 标签属性,展示 thymeleaf 模板的静态页面效果;当通过 Web 应用程序访问时,Thymeleaf 会动态地替换掉静态内容,使页面动态显示。从而可以更好地分割开前后端的开发。
搭建Demo
首先创建一个SpringBoot项目,添加lombok、SpringWeb和Thymeleaf
配置文件
在application.yml配置文件中关闭cache缓存
Thymeleaf默认会开启页面缓存,提高页面并发能力,但会导致我们修改页面不会立即被展现,所以开发中最好关闭页面缓存
server:
port: 8081
spring:
thymeleaf:
cache: false
添加thymeleaf模版
在idea的设置中添加一个thymeleaf模版
设置 → 编辑器 → 文件和代码模版
添加一个名为thymeleaf的模版
<!doctype html>
<html lang="ch" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>#[[$Title$]]#</title>
</head>
</html>
创建模版后,对着文件夹右键选择新建,就可以看到自己创建的thymeleaf模版
Thymeleaf语法的基本使用
语法标记
简单表达式:
- 变量表达式:
${...}
- 选择变量表达式:
*{...}
- 消息表达:
#{...}
- 链接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)
使用thymeleaf来渲染模版
可以通过使用thymeleaf的标签语法来达到渲染语句的效果,如下,我们要动态地渲染这个页面的title,可以使用th:text
来进行渲染
<!doctype html>
<html lang="ch" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title th:text="${title}">默认的title</title>
</head>
</html>
此时,标签语法中的title并没有被定义,故在实际页面上渲染的标题依然是默认的title
这时需要定义一个控制器来对模版进行渲染,创建一个IndexController
@Controller
public class IndexController {
@GetMapping("/index")
public String index(Model model){
model.addAttribute("title", "传递的title");
return "index";
}
}
然后通过访问控制器接口可以看到成功传递了title属性
标签语法渲染的属性可以进行字符串拼接,只需要在前后都加上|
<!doctype html>
<html lang="ch" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title th:text="|这是个${title}|">默认的title</title>
</head>
</html>
如果需要渲染页面描述和页面关键字,则可以使用th:content
标签
<head>
<meta charset="UTF-8">
<title th:text="${title}">默认的标题</title>
<meta name="description" th:content="${description}">
<meta name="keywords" th:content="${keywords}">
</head>
@GetMapping("/index")
public String index(Model model) {
model.addAttribute("title", "传递的标题");
model.addAttribute("description", "传递的描述");
model.addAttribute("keywords", "传递的关键字");
return "index";
}
渲染对象
创建一个实体类UserVO
@Data
public class UserVO {
private String username;
private Integer age;
private Integer sex;
private Boolean isVip;
private Date createTime;
private List<String> tags;
}
在controller中新建一个basic方法,来将user对象传输到页面中
@GetMapping("/basicTrain")
public String basic(Model model) {
UserVO userVO = new UserVO();
userVO.setAge(21);
userVO.setSex(1);
userVO.setCreateTime(new Date());
userVO.setTags(Arrays.asList("Java", "PHP", "Node"));
userVO.setUsername("zoi");
model.addAttribute("user", userVO);
return "basic";
}
新建basic.html,通过调用方法的形式来渲染user对象的信息
<div>
<h2 th:text="${user.getUsername()}"></h2>
<p th:text="${user.getAge()}"></p>
</div>
还可以不使用get的方式,直接使用属性名
<h2 th:text="${user.username}" ></h2>
也可以用以下方式将user定义为临时变量,然后使用*{xxx}
调用
<div th:object="${user}">
<h2 th:text="*{username}"></h2>
<p th:text="*{age}"></p>
</div>
th:if 判断
th:if
可以通过布尔值决定这个元素是否渲染,为true则渲染,false则不渲染
<p th:if="${user.isVip}">会员</p>
th:each 迭代循环
th:each
可以迭代循环出数据,在user对象中tags是一个数组,可以使用以下方式渲染
<ul>
<li th:each="tag:${user.getTags()}"
th:text="${tag}"></li>
</ul>
状态变量在th:each
属性中定义,并且包含以下数据:
- 当前的迭代索引,从0开始。这是
index
属性。 - 从1开始的当前迭代索引。这是
count
属性。 - 迭代变量中元素的总数。这是
size
财产。 - 每次迭代的iter变量。这是
current
财产。 - 当前迭代是偶数还是奇数。这些是
even/odd
布尔属性。 - 当前迭代是否是第一个。这是
first
布尔属性。 - 当前迭代是否为最后一次。这是
last
布尔属性。
th:switch 选择器
th:switch
选择语句,*代表默认
<div th:switch="${user.getSex()}">
<p th:case="'1'">男</p>
<p th:case="'2'">女</p>
<p th:case="*">默认</p>
</div>
th:href 引入静态资源
如果需要通过thymeleaf引入static目录下的静态资源可以使用@{xxx}
的方式引用
<link th:href="@{/app.css}" rel="stylesheet">
th:inline 动态渲染
通过th:inline
可以动态地渲染JavaScript的代码
<script th:inline="javascript">
const user = /*[[${user}]]*/{};
console.log(user)
</script>
同理,css也可以用这种方式渲染
<style th:inline="css">
.main\ elems {
text-align: /*[[${align}]]*/ left;
}
</style>
th:fragment 碎片(组件)
在日常开发中我们经常会将一些可以复用的部分抽离出来,避免重复开发
新建一个compoment.html
,一个文件里面可以写多个碎片,使用th:fragment
来定义
<footer th:fragment="com1">
this is com1
</footer>
<footer id="com2">
this is com2
</footer>
定义组件后,通过标签语法来渲染到html,主要有两种方式来使用碎片replace
和insert
,在index.html中编写
<!--replace-->
<div th:replace="~{component::com1}"></div>
<!--insert-->
<div th:insert="~{component::com1}"></div>
这两种方式的区别就是,replace会将新标签完全替换原本的标签,也就是说原本写th:replace
属性的标签就不会渲染出来,insert
是往这个标签内插入标签
通过选择器使用
可以直接通过选择器使用碎片,而不需要通过th:fragment
来定义
<footer id="com2">
this is com2
</footer>
然后可以直接使用它
<div th:insert="~{compoment::#com2}"></div>
注释类型
在碎片中是可以使用控制传递的数据的,比如上面的user对象,但是开发工具在compoment.html
页面中可能不能识别到user对象,我们可以打一个注释
<!--/*@thymesVar id="user" type="com.example.thymeleaf.vo.UserVO"*/-->
<h2 th:text="${user.getUsername()}"></h2>
组件传递参数
Thymeleaf中组件也是可以传递数据的
<div th:fragment="com3(message)">
<p th:text="${message}"></p>
</div>
引用组件
<div th:insert="~{compoment::com3('这是传递的数据')}"></div>
局部替换组件
我们使用一个组件的时候,想要局部替换掉这个组件里面的部分内容该怎么做呢?通过传递参数的方式传递一个组件过来,并把这个组件替换掉原本的一部分
<div th:fragment="com4(message)">
<p th:replace="${message}">原本的message</p>
</div>
使用的时候
<div th:insert="~{component::com4(~{::#message})}">
<p id="message">替换的message</p>
</div>
基本对象
ctx:上下文对象
${#ctx.request}
${#ctx.response}
${#ctx.session}
${#ctx.servletContext}
请求/会话属性
${session.xxx}
${application.xxx}
${#request.getAttribute('xxx')}
工具类
在thymeleaf里面是可以直接使用一些Java的函数的,并且你可以通过传递参数的方式把一些自己写的方法传递给页面,在里面调用也是可以的
一些可以直接的使用函数
- \#dates
- \#calendars
- \#strings
- \#numbers
- \#objects
bools
- \#arrays
- \#lists
- \#sets
- \#maps
- \#aggregates
以日期格式化来举例:
<!--日期格式化-->
<p th:text="${#dates.format(user.createTime,'yyyy-MM-dd HH:mm')}"></p>