type
Post
status
Published
date
Sep 23, 2021
slug
summary
tags
模板引擎
category
技术分享
icon
password
Thymeleaf 是 SpringBoot 官方推荐的模板引擎,和 Freemarker 相比:
  • 支持HTML原型格式,浏览器可以直接打开
  • 可以作为 HTML 片段、代码模板、右键模板等

快速入门

整合 SpringBoot

引入依赖

<!--springboot环境--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
notion image

配置

配置类解析

@ConfigurationProperties( prefix = "spring.thymeleaf" ) public class ThymeleafProperties { private static final Charset DEFAULT_ENCODING; public static final String DEFAULT_PREFIX = "classpath:/templates/"; public static final String DEFAULT_SUFFIX = ".html"; private boolean checkTemplate = true; private boolean checkTemplateLocation = true; private String prefix = "classpath:/templates/"; private String suffix = ".html"; private String mode = "HTML"; private Charset encoding; }
由配置类可知
  • 通过 @ConfigurationProperties 注解,将 application.properties 前缀为 spring.thymeleaf 的配置和这个类中的属性绑定
  • 前三个 static 变量定义了默认的编码格式、视图解析器的前缀、后缀等
    • 默认情况下html页面放在类路径下的templates下,thymeleaf将识别并自动渲染
  • 如果自己提供配置,则在 application.properties 中以 spring.thymeleaf 开始相关的配置

测试

@Controller public class TestController { @RequestMapping("/t1") public String test1(Model model){ //classpath:/templates/test.html model.addAttribute("msg","Hello,Thymeleaf"); return "test"; } }
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>测试页面</h1> <div th:text="${msg}"></div> </body> </html>
xmlns:th=http://www.thymeleaf.org xmlns:sec=http://www.thymeleaf.org/extras/spring-security xmlns:shiro=http://www.pollix.at/thymeleaf/shiro <html lang=en xmlns:th=http://www.thymeleaf.org xmlns:sec=http://www.thymeleaf.org/extras/spring-security xmlns:shiro=http://www.pollix.at/thymeleaf/shiro>

手动渲染

  1. 首先注入一个 TemplateEngine 对象,这个对象就是在 Thymeleaf 的自动化配置类中配置的(即当我们引入 Thymeleaf 的依赖之后,这个实例就有了)
  1. 然后构造一个 Context 对象用来存放变量
  1. 调用 process 方法进行渲染,该方法的返回值就是渲染后的 HTML 字符串,然后我们将这个字符串发送出去
@Autowired TemplateEngine templateEngine; @Test public void test1() throws MessagingException { Context context = new Context(); context.setVariable("username", "javaboy"); context.setVariable("position", "Java工程师"); context.setVariable("salary", 99999); String mail = templateEngine.process("mail", context); //省略邮件发送 }

Thymeleaf 指令

表达式

<div th:text="${msg}"></div> <!--不转义--> <div th:utext="${msg}"></div> <!--遍历数据--> <!--th:each每次遍历都会生成当前这个标签:官网#9--> <h4 th:each="user :${users}" th:text="${user}"></h4> <h4> <!--行内写法:官网#12--> <span th:each="user:${users}">[[${user}]]</span> </h4> </body> </html>

简单表达式

${ }
  • th:text = "${}" 直接获取对象属性
{ }
  • 可以像${ }一样使用
  • 还能通过 th:object 获取对象,然后再使用*{ }进行引用
    • <div th:text="*{user.username}"></div> <div th:objet="${user}"> <div th:text="*{username}"></div> </div>
#{} 获取国际化属性的翻译值
  • 在 resources 目录下新建两个文件:
    • messages.properties 输入:message = hello
    • messages_zh_CN.properties 输入:message = 你好
  • 然后通过#{ }引用 message,系统会根据浏览器的语言环境显示不同的值
@{ } 用于引用URL地址
  • 引用绝对URL:与普通引用等价
    • th:src="@{http://localhost:8080/hello.js}" src="http://localhost:8080/hello.js"
  • 相对URL:相对于服务器的URL
    • <script th:src="@{~/hello.js}">
  • 协议相对URL:无需加协议名称,自动根据应用选择
    • <script th:src="@{//localhost:8080/hello.js}"></script>
  • 带参数的URL:渲染成?和&分隔的参数形式
    • <script th:src="@{//localhost:8080/hello.js(name='java',age=99)}">
  • 获取应用上下文的URL
    • <script th:src="@{/hello.js}"></script>
      server.servlet.context-path属性控制

字面量

允许直接写在表达式中的字符
  • 文本:用单引号括起来' '
    • 如果文本是英文,并且不包含空格、逗号等字符,可以不用加单引号
  • 数字,布尔值(true false),null

运算符

文本运算
  • 文本使用 + 号拼接
<div th:text="'hello '+${user.username}">
  • 字面量置换:自动置换其中的变量为字符串
<div th:text="|hello ${user.username}|">
算术运算
支持加减乘除取模
th:with定义局部变量,所在的标签和子标签中能使用
<div th:with="age=(99*99/99+99-1)"> <div th:text="${age}"></div> </div>
逻辑运算
  • 布尔运算:与或非 and, or,!
  • 比较和相等:< > 标签转义为 &lt; &gt;
    • 或使用别名:gt (>) lt (<) ge (>=) le (<=) not (!) eq (==) neq/ne (!=)
  • 条件运算符:<div th:text="(条件表达式)?'yes':'no'">

内置对象

基本对象

  • #ctx:上下文对象
  • #vars: 上下文变量
  • #locale:上下文区域设置
  • #request:(仅在 Web 上下文中)HttpServletRequest 对象
  • #response:(仅在 Web 上下文中)HttpServletResponse 对象
  • #session:(仅在 Web 上下文中)HttpSession 对象
  • #servletContext:(仅在 Web 上下文中)ServletContext 对象
<!--获取内置对象--> <div th:text='${#session.getAttribute("name")}'></div>

其他对象

#execInfo:有关正在处理的模板的信息。 #messages:在变量表达式中获取外部化消息的方法,与使用#{...} 语法获得的方式相同。 #uris:转义 URL / URI 部分的方法 #conversions:执行配置的转换服务(如果有)的方法。 #dates:java.util.Date 对象的方法:格式化,组件提取等 #calendars:类似于 #dates 但是 java.util.Calendar 对象。 #numbers:用于格式化数字对象的方法。 #strings:String 对象的方法:contains,startsWith,prepending / appending 等 #objects:一般对象的方法。 #bools:布尔评估的方法。 #arrays:数组方法。 #lists:列表的方法。 #sets:集合的方法。 #maps:地图方法。 #aggregates:在数组或集合上创建聚合的方法。 #ids:处理可能重复的 id 属性的方法(例如,作为迭代的结果)

标签动态属性

给 HTML 元素设置属性值
可以一次设置多个,多个之间用 , 分隔开
--方式1 <img th:attr="src=@{/1.png},title=${user.username},alt=${user.username}"> --方式2 <img th:src="@{/1.png}" th:alt="${user.username}" th:title="${user.username}">

遍历 th:each

<table border="1"> <tr th:each="u,state : ${users}"> <td th:text="${u.username}"></td> <td th:text="${u.address}"></td> <td th:text="${state.index}"></td> <td th:text="${state.count}"></td> <td th:text="${state.size}"></td> <td th:text="${state.current}"></td> <td th:text="${state.even}"></td> <td th:text="${state.odd}"></td> <td th:text="${state.first}"></td> <td th:text="${state.last}"></td> </tr> </table>
类似于 for-each的用法,额外提供了状态对象,可获取遍历的状态:
  • index:当前的遍历索引,从0开始
  • count:当前的遍历索引,从1开始
  • size:被遍历变量里的元素数量
  • current:每次遍历的遍历变量
  • even/odd:当前的遍历是偶数次还是奇数次,返回布尔值
  • first:当前是否为首次遍历
  • last:当前是否为最后一次遍历

分支(条件渲染)

th:if

  • 接收条件表达式,或类型转换后的布尔值
    • 以下判定为false:
      数字0,字符0,字符串false off no,其他不支持类型
  • th:unless 相当于条件取反

th:switch

<td th:switch="${state.odd}"> <span th:case="true">odd</span> <span th:case="*">even</span> </td>

内联

标签直接写在InnerHTML 标签中
<div>hello [[${user.username}]]</div>
  • [[...]] 对应于 th:text (转义的 HTML)
  • [(...)] 对应于 th:utext(不进行任何转义)
内联会使得表达式直接展示在静态页面中,不像属性配置时可以直接查看效果
抵御 XSS 跨站脚本攻击模板引擎:FreeMarker