前言
- 最近因为业务需要,被拉去研究后端的项目,代码框架基于 Spring Boot,后端对我来说完全小白,需要重新学习研究…
- 出于个人习惯,会以 Blog 文章的方式做一些记录,文章内容基本来源于「 Spring Boot 从入门到精通(明日科技) 」一书,做了一些整理,更易于个人理解和回顾查找,所以大家如果希望更系统性的学习,可以阅读此书。
系列 | 文章 |
---|---|
Spring Boot 学习之路 | 📑 基础认知 |
Spring Boot 学习之路 | 📑 项目配置 |
Spring Boot 学习之路 | 📑 处理 HTTP 请求 |
Spring Boot 学习之路 | 📑 Service 层 |
Spring Boot 学习之路 | 📑 Thymeleaf 模板引擎 |
一、概述
Spring Boot 遵循“前后端分离”的设计理念。所谓的“前后端分离”中的前端指网页端、客户端,后端指服务器端。后端只提供服务接口,前端只有通过访问后端接口才能获取到数据。此外,前端还要完成页面的布局、渲染等工作。如果想让前端获取的数据可以根据用户的操作而发生变化,就需要使用动态网页技术。为此,Spring Boot 采用了 Web 模板引擎技术。Thymeleaf 是 Spring Boot 官方推荐使用的模板引擎。
Thymeleaf 是一个 Java 模板引擎,适用于 Web 开发和独立环境的服务器端。那么,什么是模板引擎呢?模板引擎是为了使用户界面与业务数据分离而生成的特定文本格式的文档,常用的文本格式有 HTML、XML 等。
Thymeleaf 的主要目标是提供一种可以被浏览器正确显示的、格式良好的模板创建方式。在实际开发中,程序开发人员可以使用 Thymeleaf 创建 XML 和 HTML 模板。所谓 XML 和 HTML 模板,指的是格式良好的 .html 文件。也就是说,Thymeleaf 把 .html 文件作为模板。与编写逻辑代码相比,程序开发人员只需要把标签属性添加到 .html 文件中,即可执行预先制定好的逻辑。
Thymeleaf 具有如下两个特点:
- Thymeleaf 在有网络、无网络的环境下都可以运行。Thymeleaf 可以直接在浏览器中打开并查看静态页面。Thymeleaf 可以通过向 HTML 标签中添加其他属性实现数据渲染。
- Thymeleaf 具有“开箱即用”的特性。Thymeleaf 直接以 .html 的格式予以显示。Thymeleaf 可以使前后端很好地分离。
二、添加 Thymeleaf
Thymeleaf 需要手动添加到 Spring Boot 项目中。添加 Thymeleaf 的方式有两种:
- 第一种是在创建项目的添加依赖界面中选择 Thymeleaf:
- 第二种是在已创建好的项目的 pom.xml 文件中添加以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
三、跳转至 .html 文件
在前面文章的实例中,控制器都是直接返回字符串,或者是跳转至其他 URL 地址。如果想让控制器跳转至项目中的某个 .html 文件,就需要使用 Thymeleaf 了。
3.1 明确 .html 文件的存储位置
Spring Boot 项目中所有页面文件都要放在 src/main/resources 目录的 templates 文件夹下。页面可能需要加载一些静态文件,例如图片、JS 文件等,静态文件需要放在与 templates 同级的 static 文件夹下。
3.2 跳转至指定的 .html 文件
前面曾介绍了两种控制器注解:@Controller 和 @RestController。@Controller 中的方法如果返回字符串,则默认访问返回值对应的地址。如果项目添加了 Thymeleaf 依赖则会改变此处跳转的逻辑,Thymeleaf 会根据返回的字符串值,寻找 templates 文件夹下同名的网页文件,并跳转至该网页文件。例如,下图所示,如果方法的返回值为“login”,Thymeleaf 在 templates 文件夹下发现了 login.html 文件,则会让其请求跳转至该文件。如果方法返回值没有对应的 .html 文件,则会抛出 TemplateInputException 异常。
说明:
想要实现此功能的控制器,必须用 @Controller 标注,不能使用 @RestController。
templates 文件夹下的 .html 文件无法通过 URL 地址直接访问,只能通过 Controller 类跳转。
html 文件可以放在 static 文件夹下,这样 .html 文件就是静态页面,可以直接通过 URL 地址访问,但无法获得动态数据。
3.3 跳转至 Thymeleaf 的默认页面
在不指定项目主页和错误页跳转规则的前提下,Thymeleaf 模板会默认将 index.html 当作项目的默认主页,将 error.html 当作项目默认错误页。如果发生的异常没有被捕捉,就自动跳转至 error.html。
注意:
默认的 index.html 和 error.html 必须在 templates 文件夹根目录下。
- 为项目添加默认首页
在 templates 文件夹下创建 index.html,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>这是 Thymeleaf 默认的首页</h1>
</body>
</html>
创建 IndexController 控制器类,如果用户访问 “/login” 地址,则必须传入 name 参数。IndexController 类的代码如下:
public class IndexController {
@RequestMapping("/login")
public String login(@RequestParam String name) {
return "您输入的用户名为:" + name;
}
}
启动项目后,打开浏览器访问 http://127.0.0.1:8080 地址,可以看到下图的默认首页。
访问地址 http://127.0.0.1:8080/login?name=David 可以看到控制器返回如下界面:
四、常用表达式和标签
Thymeleaf 提供了许多独有的标签,程序开发人员可以利用这些标签让页面显示动态的内容。Thymeleaf 也提供了几个表达式用来为标签赋值。本节将介绍一些常用的表达式和标签。
4.1 表达式
Thymeleaf 有 4 种常用的表达式,分别用于不同场景,下面分别介绍。
1. 读取属性值
后端向前端发送的数据都会放在 Model 对象中,存放格式类似键值结构,就是“属性名:属性值”的结构。在页面中可以利用 *{} 表达式通过属性名获得 Model 中属性值。表达式语法如下:
*{属性名}
例如,获取属性名为 name 的值:
*{name}
2. 读取对象
如果后端向前端发送的不是一个具体值,而是一个对象(例如日期对象、集合对象等),想要调用该对象中的属性或方法,必须使用 ${} 表达式。表达式语法如下:
${对象}
${对象.属性}
${对象.方法()}
${对象}获得的是对象,而不是一个具体值,所以需要配合遍历、定义变量等标签一起使用。${对象.方法()} 获得的是该对象方法的返回值。
3. 封装地址
如果想要在 Thymeleaf 标签中赋值具体的 URL 地址,需要用到 @{} 表达式。表达式语法如下:
@{/URL地址}
使用该表达式可以为标签定义跳转地址。
4. 插入片段
插入片段表达式的功能类似 JSP 中的 jsp:include 标签,允许程序开发人员将 A 页面中的代码插入到 B 页面中。表达式语法如下:
~{创建片段的文件名::片段名}
该表达式必须配合 th:fragment 标签,在定义完代码片段之后使用。注意该表达式的写法比较特殊,“创建片段的文件名”是代码片段所在文件的抽象名称,例如代码片段定义在 src/main/resources/templates/top/head.html 页面文件中,文件名应该写为“top/head”,不包含根目录名和后缀名。“片段名”为 th:fragment 标签定义的名称。表达式中间有两个冒号而不是一个。
4.2 标签
很多表达式都需要配合标签一起使用,Thymeleaf 提供的标签非常多,基本满足了所有动态页面的需求。下图表中列出了一些常用的标签,想要使用这些标签,就必须先在页面顶部导入标签,代码如下:
<html xmlns:th="http://www.thymeleaf.org">
导入之后就可以把 Thymeleaf 的标签以标签属性的形式写在 HTML 各元素之中。
五、向前端页面传值
Thymeleaf 从后端向前端页面传值的语法比 JSP 技术简洁许多。本节将介绍使用 Thymeleaf 向前端页面传值的两步操作。
5.1 把要传的值添加到 Model 对象中
Model 是 org.springframework.ui 包下的接口,用法类似 Map 键值对。Model 接口提供的接口如下:
程序开发人员只需为 Controller 的跳转方法添加 Model 参数,然后把要传给前端的值保存成 Model 的属性,Thymeleaf 可以自动读取 Model 里的属性值,并将其写入前端页面中。例如,把用户名 “张三” 传输给前端,可以参照如下代码:
@RequestMapping("/index")
public String show(Model model) {
model.addAttribute("name", "张三");
return "index";
}
5.2 在前端页面中获取 Model 的属性值
前端读取 Model 的属性值时需要用到 *{} 或 ${} 表达式。如果读取基本数据类型或字符串,就用*{},例如 *{name} 即可读取 Model 中名为 name 的属性值。
比如,我们做个测试:在前端页面显示用户的 IP 地址信息。
- 创建 ParameterController 控制器类,为映射 “/index” 的方法添加 Model 参数和 HttpServletRequest 参数。获取发送请求的 IP 地址、请求类型,以及请求头中的浏览器类型,将这些数据都保存在 Model 的属性中,最后跳转至 main.html。
ParameterController 类的代码如下:
@Controller
public class ParameterController {
@RequestMapping("/index")
public String index(Model model, HttpServletRequest request) {
model.addAttribute("ip", request.getRemoteAddr()); // 记录请求 IP 地址
model.addAttribute("method", request.getMethod()); // 记录请求类型
String brow = "未知";
String userAgent = request.getHeader("User-Agent").toLowerCase(); // 读取请求头
if (userAgent.contains("Chrome")) { // 如果包含谷歌浏览器名称
brow = "谷歌浏览器";
} else if (userAgent.contains("Firefox")) { // 如果包含火狐浏览器名称
brow = "火狐浏览器";
}
model.addAttribute("brow", brow); // 记录浏览器识别结果
return "main";
}
}
- 在 main.html 中获取 Model 中的 IP 地址、请求类型和浏览器类型的值,展示在页面中。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p th:text=" '您的 IP 地址:' + ${ip}"></p>
<p th:text=" '您提供的方式:' + ${method}"></p>
<p th:text=" '您使用的浏览器:' + ${brow}"></p>
</body>
</html>
启动项目后,访问 http://127.0.0.1:8080/index 地址。