本文主要对SpringBoot2.x集成Thymeleaf及其常用语法进行简单总结,其中SpringBoot使用的2.4.5
版本。
一、Thymeleaf简介
Thymeleaf是面向Web和独立环境的现代服务器Java模板引擎,能够处理HTML,XML,JavaScript,CSS甚至纯文本。
Thymeleaf旨在提供一个优雅的、高度可维护的创建模板的方式。为了实现这一目标,Thymeleaf建立在自然模板的概念上,将其逻辑注入到模板文件中,不会影响模板设计原型。这改善了设计的沟通,弥合了设计和开发团队之间的差距。
Thymeleaf从设计之初就遵循Web标准——特别是HTML5标准,如果需要,Thymeleaf允许创建完全符合HTML5验证标准的模板。
二、集成Thymeleaf
通过Maven新建一个名为springboot-thymeleaf
的项目。
1.引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
</dependency>
2.编写配置文件
spring:
thymeleaf:
# 在构建URL时附加到视图名称的前缀,默认为classpath:/templates/
prefix: classpath:/templates/
# 在构建URL时附加到视图名称的后缀,默认为.html
suffix: .html
# 模板模式,默认为HTML
mode: HTML
# 模板文件编码,默认为UTF-8
encoding: UTF-8
# 是否启用模板缓存,默认为true,表示启用,false不启用
cache: false
# 在呈现模板之前是否检查模板存在与否,默认为true
check-template: true
# 是否检查模板位置存在与否,默认为true
check-template-location: true
更多的配置可以查看ThymeleafProperties
类:
3.准备模板
首先按照配置文件中配置的模板前缀在resources
下创建一个templates
目录,用于存放模板。然后创建如下名为hello.html
的模板:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Hello Thymeleaf</title>
</head>
<body>
<div>
<span th:text="${hello}">th:text文本替换会转义html标签,不解析html</span>
</div>
<hr/>
<div>
<span th:utext="${hello}">th:utext文本替换不会转义html标签,会解析html</span>
</div>
</body>
</html>
标签中的
xmlns:th="http://www.thymeleaf.org
声明使用Thymeleaf标签。th:text
属性会计算表达式的值将结果设置为标签的标签体。但它会转义HTML标签,HTML标签会直接显示在浏览器上。th:utext
属性不会转义HTML标签,HTML标签会被浏览器解析。${hello}
是一个变量表达式,它包含一个OGNL(Object-Graph Navigation Language)的表达式,它会从上下文中获取名为hello
的变量,然后在模板上进行渲染。
4.Controller层
创建Controller并将模板中要获取的变量设置到Model对象中,如果Controller类上使用的是@Controller
注解,则可以返回跟模板名称相同的字符串(不包括前缀和后缀),视图解析器会解析出视图具体地址并生成视图,然后返回给前端控制器进行渲染:
package com.rtxtitanv.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
/**
* @author rtxtitanv
* @version 1.0.0
* @name com.rtxtitanv.controller.ThymeleafController
* @description ThymeleafController
* @date 2021/7/3 19:23
*/
@Controller
public class ThymeleafController {
@GetMapping("/hello")
public String hello(Model model) {
model.addAttribute("hello", "Hello Thymeleaf
");
return "hello";
}
}
运行项目,浏览器访问http://localhost:8080/hello,发现数据成功渲染到模板:
如果Controller类上使用的是@RestController
注解,则需要将视图添加到ModelAndView对象中并返回:
package com.rtxtitanv.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
/**
* @author rtxtitanv
* @version 1.0.0
* @name com.rtxtitanv.controller.TestController
* @description TestController
* @date 2021/7/3 19:43
*/
@RequestMapping("/test")
@RestController
public class TestController {
@GetMapping("/hello")
public ModelAndView hello() {
ModelAndView modelAndView = new ModelAndView("hello");
modelAndView.addObject("hello", "hello thymeleaf
");
return modelAndView;
}
}
运行项目,浏览器访问http://localhost:8080/test/hello,发现数据成功渲染到模板:
三、Thymeleaf常用语法
1.标准表达式
(1)变量表达式
${}
表达式实际上是在上下⽂中包含的变量的映射上执行的OGNL(Object-Graph Navigation Language)对象。例如:${session.user.name}
。
在Spring MVC启用的应用程序中,OGNL将被替换为SpringEL,但其语法与OGNL相似(实际上,在大多数常见情况下完全相同)。
模板variable.html
如下:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>变量表达式</title>
</head>
<body>
<p>变量表达式:${}</p>
<div>
<p>id: <span th:text="${user.id}"></span></p>
<p>username: <span th:text="${user.username}"></span></p>
<p>password: <span th:text="${user.password}"></span></p>
</div>
</body>
</html>
User实体类:
package com.rtxtitanv.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author rtxtitanv
* @version 1.0.0
* @name com.rtxtitanv.model.User
* @description User
* @date 2021/7/3 19:37
*/
@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {
private Long id;
private String username;
private String password;
}
ThymeleafController
中新增以下方法:
@GetMapping("/variable")
public String variable(Model model) {
model.addAttribute("user", new User(1L, "赵云", "qwe123"));
return "variable";
}
效果:
在${}
表达式中还可以使用基本对象和工具类对象。这些对象都以#
开头。基本对象:
#ctx
:上下文对象。#vars
:上下文变量。#locale
:上下文区域设置。#request
:(仅在Web Contexts中)HttpServletRequest对象。#response
:(仅在Web上下⽂中)HttpServletResponse对象。#session
:(仅在Web上下⽂中)HttpSession对象。#servletContext
:(仅在Web上下⽂中)ServletContext对象。
工具类对象:
#execInfo
:有关正在处理的模板的信息。#messages
:用于在变量表达式中获取外部化消息的方法,与使用#{}语法获取的方式相同。#uris
:转义URL/URI部分的方法。#conversions
:执行配置的转换服务的方法。#dates
:java.util.Date
对象的方法。#calendars
:类似于#dates
,但对应java.util.Calendar
对象。#numbers
:用于格式化数字对象的方法。#strings
:字符串对象的方法。#objects
:一般对象的方法。#bools
:布尔相关方法。#arrays
:Array的方法。#lists
:List的方法。#sets
:Set的方法。#maps
:Map的方法。#aggregates
:在数组或集合上创建聚合的方法。#ids
:处理可能重复的id属性的方法。
这些对象的详细方法可以查看官方文档:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#appendix-a-expression-basic-objects。
(2)选择表达式(星号语法)
星号语法*{}
计算所选对象而不是整个上下文的表达式。也就是说,只要没有选定的对象(选定对象为th:object
属性的表达式结果),$
和*
语法就会完全相同。
模板asterisk.html
如下:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>选择表达式(星号语法)</title>
</head>
<body>
<p>*语法</p>
<div th:object="${user}">
<p>id: <span th:text="*{id}"></span></p>
<p>username: <span th:text="*{username}"></span></p>
<p>password: <span th:text="*{password}"></span></p>
</div>
<p>$语法</p>
<div>
<p>id: <span th:text="${user.id}"></span></p>
<p>username: <span th:text="${user.username}"></span></p>
<p>password: <span th:text="${user.password}"></span></p>
</div>
<p>$和*混合使用</p>
<div th:object="${user}">
<p>id: <span th:text="*{id}"></span></p>
<p>username: <span th:text="${user.username}"></span></p>
<p>password: <span th:text="*{password}"></span></p>
</div>
<p>对象选择到位时所选对象将作为#object表达式变量可⽤于$表达式</p>
<div th:object="${user}">
<p>id: <span th:text="${#object.id}"></span></p>
<p>username: <span th:text="${user.username}"></span></p>
<p>password: <span th:text="*{password}"></span></p>
</div>
<p>没有执⾏对象选择时$和*语法等效</p>
<div>
<p>id: <span th:text="*{user.id}"></span></p>
<p>username: <span th:text="*{user.username}"></span></p>
<p>password: <span th:text="*{user.password}"></span></p>
</div>
</body>
</html>
ThymeleafController
中新增以下方法:
@GetMapping("/asterisk")
public String star(Model model) {
model.addAttribute("user", new User(1L, "赵云", "qwe123"));
return "asterisk";
}
效果:
(3)URL表达式
URL表达式的语法为@{}
。使用th:href
属性可以对链接进行渲染。
模板url.html
如下:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>URL表达式</title>
</head>
<body>
<ol>
<li><a href="user/one.html" th:href="@{/user/one(id=${user.id})}">设置单个参数</a></li>
<li><a href="user/list.html" th:href="@{/user/list(username=${user.username},password=${user.password})}">设置多个参数</a></li>
<li><a href="user/one.html" th:href="@{/user/one/{id}(id=${user.id})}">URL路径中也允许使⽤变量模板(rest风格参数)</a></li>
<li><a href="user/update.html" th:href="@{${url}(id=${user.id})}">URL基数也可以是计算另⼀个表达式的结果</a></li>
<li><a href="store/user/update.html" th:href="@{'/store' + ${url}(id=${user.id})}">url基数也可以是计算另⼀个表达式的结果</a></li>
</ol>
<hr/>
<form id="login-form" th:action="@{/hello}">
<button>提交</button>
</form>
</body>
</html>
注意:
ThymeleafController
中新增以下方法:
@GetMapping("/url")
public String url(Model model) {
model.addAttribute("user", new User(1L, "赵云", "qwe123"));
model.addAttribute("url", "/user/update");
return "url";
}
效果:
从上到下依次点击5个链接和提交表单的结果: