SpringBoot使用Thymeleaf模板引擎

1、认识Thymeleaf
SpringBoot主要支持Thymeleaf、Freemarker、Mustache、 Groovy Templates等模板引擎。Thymeleaf可以轻易地与SpringMVC等Web框架进行集成。Thymeleaf语法并不会破坏文档的结构,所以Thymeleaf模板依然是有效的HTML文档。模板还可以被用作工作原型,Thymeleaf会在运行期内替换掉静态值。它的模板文件能直接在浏览器中打开并正确显示页面,而不需要启动整个Web应用程序。

Thymeleaf的使用非常简单。比如,要输出“pan_junbiao的博客”字符串,可以很简单地在模板文件中加入以下代码:

<p th:text="${userName}?:'pan_junbiao的博客'"></p>
其中,“<p th:text="${userName}>”用来接收控制器传入的参数“userName”。如果控制器向模板传入了参数,则Thymeleaf会用“userName”参数的值替换掉“pan_junbiao的博客”。

 

2、使用Thymeleaf
(1)引入依赖

使用Thymeleaf,首先需要引入依赖。直接在pom.xml文件中加入以下依赖即可。

<!-- 引入Thymeleaf模板引擎 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
(2)在模板文件中加入解析

在加入依赖后,还需要在HTML文件中加入命名空间,这样就能完成Thymeleaf的标签的渲染。命名空间如下:

<html lang="en" xmlns:th="http://www.thymeleaf.org">
以下代码是一个简单完整的Thymeleaf模板文件。

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>用户信息</title>
<meta name="author" content="pan_junbiao的博客">
</head>
<body>
<p th:text="${userName}?:'pan_junbiao的博客'"></p>
</body>
</html>
(3)配置视图解析器

在application.properties配置文件中,可以配置Thymeleaf模板解析器属性,如以下代码:

spring.thymeleaf.mode=HTML5
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.servlet.content-type=text/html
#为便于测试,在开发时需要关闭缓存
spring.thymeleaf.cache=false
在application.yml的配置如下:

spring:
thymeleaf:
mode: HTML5
encoding: UTF-8
cache: false #使用Thymeleaf模板引擎,关闭缓存
servlet:
content-type: text/html
Thymeleaf检查HTML格式很严格。如果HTML格式不对,则会报错。如果想禁止这种严格的语法检查模式,这可以在application.properties配置文件中加入“spring.thymeleaf.mode=LEGACYHTML5”来解决。在开发过程中,一般将Thymeleaf的模板缓存设置为关闭,即在application.properties配置文件中加入“spring.thymeleaf.cache=false”。否则,修改之后可能不会及时显示修改后的内容。

【示例】使用Thymeleaf模板引擎,显示用户信息。

(1)创建实体类

在SpringBoot项目中,创建entity目录(实体类层),并创建User(用户信息实体类)。

package com.pjb.thymeleafdemo.entity;

/**
* 用户信息实体类
* @author pan_junbiao
**/
public class User
{
private int id; //用户编号
private String userName; //用户姓名
private String blogUrl; //博客地址
private String blogInfo; //博客信息
private String role; //用户角色

//省略getter与setter方法...
}

(2)创建Controller控制器

创建controller目录(控制器层),并创建UserController(用户信息控制器类)。

package com.pjb.thymeleafdemo.controller;

import com.pjb.thymeleafdemo.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

/**
* 用户信息控制器类
* @author pan_junbiao
**/
@Controller
@RequestMapping("/user")
public class UserController
{
/**
* 获取用户信息
*/
@RequestMapping("/getUser")
public String getUser(Model model)
{
//创建用户信息
User user = new User();
user.setId(1);
user.setUserName("pan_junbiao的博客");
user.setBlogUrl("https://blog.csdn.net/pan_junbiao");
user.setBlogInfo("您好,欢迎访问 pan_junbiao的博客");
user.setRole("admin");

//将用户信息保存到Model对象中
model.addAttribute("user",user);

//返回页面
return "/user/userInfo";
}
}

(2)创建HTML页面

在resources/templates目录下,创建user目录,并在该目录下创建userInfo.html(用户信息页面)。

<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>用户信息</title>
<meta name="author" content="pan_junbiao的博客">
</head>
<body>
<h3>使用Thymeleaf模板引擎</h3>
用户编号:<span th:text="${user.id}"></span><br/>
用户姓名:<span th:text="${user.userName}"></span><br/>
博客地址:<span th:text="${user.blogUrl}"></span><br/>
博客信息:<span th:text="${user.blogInfo}"></span><br/>
</body>
</html>
执行结果:

 

 

 

3、基础语法
3.1 常用th标签
(1)th:text
<div th:text="${userName}"></div>
它用于显示控制器传入的userName值。

如果userName不存在,要显示默认值,则使用以下代码:

<div th:text="${userName}?:'pan_junbiao的博客'"></div>
(2)th:object
它用于接收后台传过来的对象,如以下代码:

th:object="${userName}"
(3)th:action
它用来指定表单提交地址。

<form th:action="@{/user/}+${user.id}" method="post">
</form>
(4)th:value
它用对象将id的值替换为value的属性值。

<input type="text" th:value="${user.id}" name="id"/>
(5)th:field
它用来绑定后台对象和表单对象数据。Thymeleaf里的“th:field”等同于“th:name”和“th:value”。

<input type="text" id="userName" name="userName" th:field="${user.userName}" />
(6)th:block
th:block 可以排除标签(不写在标签中)直接显示内容。

例如在循环遍历内容时,可以使用 th:block 排除外层标签。

<th:block th:each="user:${userList}">
用户编号:<span th:text="${user.id}"></span><br/>
用户姓名:<span th:text="${user.userName}"></span><br/>
博客地址:<span th:text="${user.blogUrl}"></span><br/>
博客信息:<span th:text="${user.blogInfo}"></span><br/>
</th:block>
(7)th:attr
th:attr 可以将数据作为html标签的一个属性存起来。

<input id="male" name="sex" type="radio" value="1" th:attr="checked=${staffModel.sex==1}"/>
<label for="male">男</label>
<input id="female" name="sex" type="radio" value="2" th:attr="checked=${staffModel.sex==2}"/>
<label for="female">女</label>
等价于:

<input id="male" name="sex" type="radio" value="1" th:checked="${staffModel.sex==1}"/>
<label for="male">男</label>
<input id="female" name="sex" type="radio" value="2" th:checked="${staffModel.sex==2}"/>
<label for="female">女</label>

3.2 Thymeleaf中的URL写法
Thymeleaf是通过语法@{...}来处理URL的,需要使用“th:href”和“th:src”等属性,如以下代码:

<a th:href="@{https://blog.csdn.net/pan_junbiao}">pan_junbiao的博客</a>
<a th:href="@{js/jquery-3.4.1.min.js}">默认访问static目录下的js文件夹</a>
3.3 用Thymeleaf进行条件求值
Thymeleaf通过“th:if”和“th:unless”属性进行条件判断。在下面的例子中,<a>标签只有在“th:if”中的条件成立时才显示。

<a th:href="@{/login}" th:if="${session.user == null}">登录</a>
“th:unless”与“th:if”恰好相反——只有当表达式中的条件不成立时才显示其内容。在下方代码中,如果用户session为空,则不显示登陆连接。

<a th:href="@{/login}" th:unless="${session.user == null}">登录</a>
3.4 Switch
Thymeleaf支持Switch结构,如以下代码:

<div th:switch="${user.role}">
<p th:case="admin">管理员</p>
<p th:case="vip">vip会员</p>
<p th:case="*">普通会员</p>
</div>
在Switch结构中,“*”表示默认情况。

3.5 Thymeleaf中的字符串替代
有时需要对字符串中的某一处地方进行替换,可以通过字符串拼接操作完成,如下代码:

<span th:text="'您好,欢迎访问'+${user.userName} + '!'"></span>
或:

<span th:text="|您好,欢迎访问${user.userName}!|"></span>
上面的第2种形式限制比较多,|...|中只能包括变量表达式${...},不能包含其他常量、条件表达式等。

3.6 Thymeleaf的运算符
(1)算数运算符

如果要在模板中进行算数运算,则可以用下面的写法。

<span th:text="1+3"></span><br/>
<span th:text="9%2"></span><br/>
(2)条件运算符 th:if

下方代码演示了if判断。

<div th:if="${user.role} eq admin">
<span>欢迎您,管理员</span>
</div>
<div th:if="${user.role} eq vip">
<span>欢迎您,vip会员</span>
</div>
eq是判断表达式,代表等于。其他的判断表达式如下:

gt:大于。
ge:大于或等于。
eq:等于。
lt:小于。
le:小于或等于。
ne:不等于。

4、处理循环遍历
4.1 遍历对象(Object)
在开发过程中,经常会遇到遍历对象的情况,可以通过“tth:each="user:${user}"”标签来处理。以下代码是遍历从控制器中传来的用户对象。

<div th:each="user:${user}">
用户编号:<span th:text="${user.id}"></span><br/>
用户姓名:<span th:text="${user.userName}"></span><br/>
博客地址:<span th:text="${user.blogUrl}"></span><br/>
博客信息:<span th:text="${user.blogInfo}"></span><br/>
</div>
外层使用 th:block 标签,则可以排除标签(不写在标签中)直接显示内容。

<th:block th:each="user:${user}">
用户编号:<span th:text="${user.id}"></span><br/>
用户姓名:<span th:text="${user.userName}"></span><br/>
博客地址:<span th:text="${user.blogUrl}"></span><br/>
博客信息:<span th:text="${user.blogInfo}"></span><br/>
</th:block>

4.2 遍历列表(List)
要处理List,也使用“th:each="item:${userList}"”。

<div th:each="user:${userList}">
用户编号:<span th:text="${user.id}"></span><br/>
用户姓名:<span th:text="${user.userName}"></span><br/>
博客地址:<span th:text="${user.blogUrl}"></span><br/>
博客信息:<span th:text="${user.blogInfo}"></span><br/>
</div>
迭代下标变量用法:

状态变量定义在一个th:每个属性和包含以下数据:
当前迭代索引,从0开始。这是索引属性。index
当前迭代索引,从1开始。这是统计属性。count
元素的总量迭代变量。这是大小属性。 size 
iter变量为每个迭代。这是目前的财产。 current 
是否当前迭代是奇数还是偶数。这些even/odd的布尔属性。  
是否第一个当前迭代。这是first布尔属性。  
是否最后一个当前迭代。这是last布尔属性。
用法实例:

<table>
<tr>
<th>序号</th>
<th>用户姓名</th>
<th>博客地址</th>
<th>博客信息</th>
</tr>
<tr th:each="user,userStat:${userList}" th:class="${userStat.odd}?'odd':'even'">
<td th:text="${userStat.index}"></td>
<td th:text="${user.userName}"></td>
<td th:text="${user.blogUrl}"></td>
<td th:text="${user.blogInfo}"></td>
</tr>
</table>

4.3 遍历数组(Array)
使用“th:each="item:${userArray}"”标签来遍历数组。

<div th:each="item:${userArray}">
<li th:text="${item}"></li>
</div>

4.4 遍历集合(Map)
集合通过“th:text="${item.key}”显示集合的key,通过“th:text="${item.value}”显示集合的值。

<!--遍历key-->
<div th:each="item:${userMap}">
<li th:text="${item.key}"></li>
</div>

<!--遍历value-->
<div th:each="item:${userMap}">
<li th:text="${item.value}"></li>
</div>

<!--遍历key-value-->
<div th:each="item:${userMap}">
<li th:text="${item}"></li>
</div>

5、处理公共代码块
一个网页的结构基本可以分为上(header)、中(body)、下(footer)三个部分。在一般情况下,header和footer的信息在各个页面都会重复显示,如果每个页面都复制一份代码则太麻烦了。

Thymeleaf模板引擎提供了th:fragment、th:replace、th:include标签用来处理重复的代码块。

1、使用th:fragment标记重复的代码块

创建common.html页面,在该页面中使用th:fragment标记重复的代码块,代码如下:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<div class="header" th:fragment="header">
公共 header
</div>

<div class="footer" th:fragment="footer">
公共 footer
</div>
</html>
2、调用重复代码块

在需要调用的地方,使用th:replace或th:include标签根据th:fragment标记的值来调用,如以下代码:

<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>首页</title>
<meta name="author" content="pan_junbiao的博客">
</head>
<body>
<div>replace调用方式:</div>
<div th:replace="~{common :: header}"></div>
<div>
<p>您好,欢迎访问 pan_junbiao的博客</p>
<p>https://blog.csdn.net/pan_junbiao</p>
</div>
<div>include调用方式:</div>
<div th:include="~{common :: footer}"></div>
</body>
</html>

执行结果:

 

 

th:replace和th:include标签都可以调用公共代码。它们的区别如下:

th:replace标签:替换当前标签为模板中的标签。比如上面用th:replace标签,则代码替换为:

<div class="header">
公共 header
</div>
th:include标签:只加载模板的内容。比如上面用th:include标签,则代码替换为:

<div>
公共 footer
</div>

6、Thymeleaf将后端返回的数据绑定给JS变量
Thymeleaf还可以将后端返回的数据绑定给JS变量,使用表达式,如下:

var userName = [[${userName}]];
【示例】在JS中使用Thymeleaf获取后端返回的数据。

(1)后端控制器

/**
* 用户信息控制器
* @author pan_junbiao
**/
@Controller
@RequestMapping("/user")
public class UserController
{
@RequestMapping("/getUserName")
public String getUserName(HttpServletRequest request)
{
request.setAttribute("userName","pan_junbiao的博客");
return "user.html";
}
}
(2)前端JS脚本

<script th:inline="javascript">
var userName = [[${userName}]];
alert(userName);
</script>
执行结果:

 

 

 

7、解决IDEA中使用Thymeleaf页面变量报错问题
IDEA在使用Thymeleaf页面编写变量,如${user.id}会出现红色波浪下划线错误,提示:Validates unresolved references and invalid expressions.

解决方法:

菜单:File → Settings → Editor → Inspections,将Thymeleaf的检测关闭。

 

posted @ 2024-04-22 09:54  XiangdxDu  阅读(152)  评论(0编辑  收藏  举报