Thymeleaf 模板引擎使用


模板引擎是为了使用户看到的页面与业务数据(内容)分离而产生的一种模板技术,它可以生成特定格式的文档,用于网站的模板引擎会生产出标准的 HTML 静态页面内容。在 Java Web 开发技术栈中,常见的模板引擎有 FreeMarker、Velocity、Thymeleaf 等,JSP 也可以理解为一种模板引擎技术。Thymeleaf 官方学习文档为:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html。

入门使用

?? SpringBoot 引入 Thymeleaf 依赖


    org.springframework.boot
    spring-boot-starter-thymeleaf

?? 在 application.properties 进行 Thymeleaf 配置

# 页面缓存设置,默认值为 true(开发中方便调试设置为 false,上线稳定后应保持默认 true)
spring.thymeleaf.cache=false

# 模板编码,默认值为 UTF-8
spring.thymeleaf.encoding=UTF-8
# 指定模板页面的存放路径,默认值为 classpath:/templates/
spring.thymeleaf.prefix=classpath:/templates/
# 指定模板页面名称的后缀,默认值为 .html
spring.thymeleaf.suffix=.html
# 指定文本类型,默认值为 text/html 
spring.thymeleaf.servlet.content-type=text/html
# 应用于模板的模板模式,默认值为 HTML
spring.thymeleaf.mode=HTML

?? 创建模板文件

在 resources/templates 目录新建模板文件 test.html,新增文件后,首先在模板文件的标签中导入 Thymeleaf 的名称空间:


导入该名称空间主要是为了 Thymeleaf 的语法提示和 Thymeleaf 标签的使用,最终的模板文件如下:




    
    Thymeleaf Test


    

显示测试字段

?? 编辑 Controller 代码

@Controller
public class ThymeleafController {

    @GetMapping("/hello")
    public String hello(Model model) {
        model.addAttribute("test", "这里是一个测试!");
        return "test";
    }
}

?? 启动并访问

访问localhost:8080/hello,可以看到原本的

标签中的内容已经被替换为这里是一个测试!

?? 模板解读

上述模板中读取动态数据并渲染的语句如下:

显示测试字段

该模板语句中包含三块内容:

  1. html 标签
  2. Thymelaf 模板引擎的 th 标签
  3. Thymelaf 表达式

前半部分的

为 html 的标签,后半部分为 Thymeleaf 属性标签和表达式语法。th:text表示文本替换,${test}表示读取后台设置的 test 字段,该模板语句的作用就是动态的将

标签中的内容替换为后台设置的 test 字段内容。

Thymeleaf 模板文件的编写规则如下:

  • 任意的 Thymeleaf 属性标签th:*需要写在 html 标签体中(th:block除外)
  • Thymleaf 表达式写在 Thymeleaf 属性标签中

th:* 替换属性值

前面我们使用th:text进行文本替换,除此之外还提供了其他的标签属性来替换 HTML5 原生属性的值,具体信息可以查看 thymeleaf-attributes。下面介绍一下通过 Thymeleaf 语法修改属性值,代码如下:

?? 编辑 test.html 模板文件




    
    Thymeleaf Test




text 标签

th:text 标签演示

th:utext 标签演示

id、name、value 标签
class、href 标签
链接

?? 编辑 Controller 代码

@Controller
public class ThymeleafController {

    @GetMapping("/hello")
    public String hello(Model model) {
        model.addAttribute("th_text", "thymeleaf-text");
        model.addAttribute("th_utext", "thymeleaf-utext");

        model.addAttribute("th_id", "thymeleaf-id");
        model.addAttribute("th_name", "thymeleaf-name");
        model.addAttribute("th_value", "thymelaf-value");

        model.addAttribute("th_class", "thymeleaf-class");
        model.addAttribute("th_href", "https://www.baidu.com");
        return "test";
    }
}

? 启动并访问

访问localhost:8080/hello,网页显示:

查看展示给客户端的网页源代码:



    
    Thymeleaf Test




text 标签

<a href='https://www.baidu.com'>thymeleaf-text</a>

thymeleaf-utext

id、name、value 标签
class、href 标签
链接

Thymeleaf 语法规则

Thymleaf 官方对标准表达式特性总结如下,具体可以查看 Standard Expression Syntax。

  • 表达式语法

    • 变量表达式: ${...}
    • 选择表达式: *{...}
    • 信息表达式: #{...}
    • 链接 URL 表达式: @{...}
    • 分段表达式: ~{...}
  • 字面量

    • 字符串: 'one text', 'Another one!' ...
    • 数字: 0, 34, 3.0, 12.3 ...
    • 布尔值: true, false
    • Null 值: null
    • 字面量标记:one, sometext, main ...
  • 文本运算

    • 字符串拼接: +
    • 字面量置换: |The name is ${name}|
  • 算术运算

    • 二元运算符: +, -, *, /, %
    • 负号(一元运算符): (unary operator): -
  • 布尔运算

    • 二元运算符: and, or
    • 布尔非(一元运算符): !, not
  • 比较运算

    • 比较: >, <, >=, <= (gt, lt, ge, le)
    • 相等运算符: ==, != (eq, ne)

    比较运算符也可以使用转义字符,比如大于号,所以 Thymeleaf 语法中>等价于>

  • 条件运算符

    • If-then: (if) ? (then)
    • If-then-else: (if) ? (then) : (else)
    • Default: (value) ?: (defaultvalue)
  • 特殊语法

    • 无操作: _

简单语法使用

下面主要介绍字面量及简单的运算操作,包括字符串、数字、布尔值等常用的字面量及常用的运算和拼接操作,代码如下:

?? 编辑 test.html 模板文件




    
    Thymeleaf Test



基本类型操作(字符串):

一个简单的字符串:default text.

字符串连接:default text.

字符串连接:default text.

基本类型操作(数字):

一个简单的数字:1000.

算术运算: 2019 + 1 = 0.

算术运算: 14 - 1 = 0.

算术运算: 673 * 3=0.

算术运算: 39 ÷ 3=0.

基本类型操作(布尔值):

一个简单的数字比较:2019 > 2018,结果为:false.

字符串比较:thymeleafText == 'hello world',结果为:false.

数字比较:13 == 39 / 3,结果为:false.

?? 编辑 Controller 代码

@Controller
public class ThymeleafController {

    @GetMapping("/hello")
    public String hello(Model model) {
        model.addAttribute("thymeleafText", "hello world");
        model.addAttribute("number1", 2019);
        model.addAttribute("number2", 3);
        return "test";
    }
}

?? 启动并访问

访问localhost:8080/hello,网页显示:


变量表达式${}

变量表达式即 OGNL 表达式或 Spring EL 表达式,作用是获取模板中与后端返回数据所绑定对象的值,写法为 ${...},这是最常见的一个表达式,在取值赋值、逻辑判断、循环语句中都可以使用该表达式。

简单使用

变量表达式可以是 OGNL 表达式,${...}不但可以访问基本数据类型的变量值,还可以访问对象的属性值,示例如下:


${person.father.name}


${person['father']['name']}


${countriesByCode.ES}
${personsByName['Jim'].age}


${personsArray[0].name}


${person.createCompleteName()}
${person.createCompleteNameWithSeparator('-')}

下面使用变量表达式${...}获取后端返回的对象、数组和集合属性值,代码如下:

?? 编辑 test.html 模板文件




    
    Thymeleaf Test



访问普通属性

name:Alice

name:Alice

name:Alice

访问数组和 List 集合

hobbies1:singing

hobbies2:singing

访问 Map 集合

hobbies3:singing

hobbies3:singing

hobbies3:singing

?? 编辑 Controller 代码

public class Person {
    private String name;
    private Integer age;
    private String[] hobbies1;
    private List hobbies2;
    private Map hobbies3;
    
    // 略写 setter 和 getter 方法
}
@Controller
public class ThymeleafController {

    @GetMapping("/hello")
    public String hello(Model model) {
        Map hobbies = new HashMap<>();
        hobbies.put("hobby1", "dancing");
        
        Person person = new Person();
        person.setName("Bob");
        person.setHobbies1(new String[]{"dancing"});
        person.setHobbies2(Arrays.asList("dancing"));
        person.setHobbies3(hobbies);
        
        model.addAttribute("person", person);
        return "test";
    }
}

?? 启动并访问

访问localhost:8080/hello,网页显示:

#### 复杂使用

? 使用内置对象

Thymeleaf 为变量所在域提供了一些内置对象,变量表达式${...}可以直接使用:

  • #ctx:上下文对象

  • #vars:上下文变量

  • #locale:上下文区域设置

  • #request:HttpServletRequest 对象(仅限 Web Context)

  • #response:HttpServletResponse 对象(仅限 Web Context)

  • #session:HttpSession 对象(仅限 Web Context)

  • #servletContext:ServletContext 对象(仅限 Web Context)

具体使用代码如下:




    
    Thymeleaf Test



default text

default text

@Controller
public class ThymeleafController {

    @GetMapping("/hello")
    public String hello(HttpServletRequest request, HttpSession session) {
        request.setAttribute("requestObject", "读取 request 域内容");
        session.setAttribute("sessionObject", "读取 session 域内容");
        return "test";
    }
}

访问localhost:8080/hello,网页显示:

? 使用内置工具类

同时,Thymeleaf 还提供了一系列 Utility 工具对象(内置于 Context 中),${...}可以直接访问:

  • #dates:日期格式化内置对象,具体方法可以参照java.util.Date

  • #calendars:类似于#dates,但是是java.util.Calendar类的方法

  • #numbers:数字格式化

  • #strings:字符串格式化,具体方法可以参照java.lang.String,如 startsWith、contains等

  • #bools:判断 boolean 类型的工具

  • #arrays:数组操作的工具

  • #lists:列表操作的工具,参照java.util.List

  • #sets:Set操作工具,参照java.util.Set

  • #maps:Map操作工具,参照java.util.Map

具体使用代码如下:




    
    Thymeleaf Test



#dates 工具类测试

year :

month :

day :

hour :

minute :

second :

格式化:

yyyy-MM-dd HH:mm:ss 格式化:

#strings 工具类测试

testString初始值 :

toUpperCase :

toLowerCase :

equalsIgnoreCase :

indexOf :

substring :

startsWith :

contains :

#bools 工具类测试

#arrays 工具类测试

length :

contains :

containsAll :

循环读取 :

#lists 工具类测试

size :

contains :

sort :

循环读取 :

#maps 工具类测试

size :

containsKey :

containsValue :

读取map中键为id2的值 :

@Controller
public class ThymeleafController {

    @GetMapping("/hello")
    public String hello(Model model) {
        model.addAttribute("testDate", new Date());
        model.addAttribute("testString", "SpringBoot Thymeleaf 学习");
        model.addAttribute("testBool", true);
        model.addAttribute("testArray", new Integer[]{2018, 2019, 2020, 2021});
        model.addAttribute("testList", Arrays.asList("Spring", "Spring Boot", "Thymeleaf", "MyBatis", "Java"));

        MaptestMap = new HashMap<>();
        testMap.put("id1", "Windows");
        testMap.put("id2", "Linux");
        testMap.put("id3", "Mac");
        model.addAttribute("testMap", testMap);

        return "test";
    }
}

访问localhost:8080/hello,网页显示:

#dates 工具类测试
year : 2020
month : 11
day : 8
hour : 17
minute : 28
second : 46
格式化: 2020年11月8日 CST 下午5:28:46
yyyy-MM-dd HH:mm:ss 格式化: 2020-11-08 17:28:46

#strings 工具类测试
testString初始值 : SpringBoot Thymeleaf 学习
toUpperCase : SPRINGBOOT THYMELEAF 学习
toLowerCase : springboot thymeleaf 学习
equalsIgnoreCase : false
indexOf : 2
substring : gBoo
startsWith : true
contains : true
    
#bools 工具类测试
true

#arrays 工具类测试
length : 4
contains : false
containsAll : true
循环读取 : 2018 2019 2020 2021

#lists 工具类测试
size : 5
contains : false
sort : [Java, MyBatis, Spring, Spring Boot, Thymeleaf]
循环读取 : Spring Spring Boot Thymeleaf MyBatis Java
    
#maps 工具类测试
size : 3
containsKey : true
containsValue : true

读取map中键为id2的值 : Linux

选择表达式*{}

选择表达式和变量表达式类似,不过它会用一个预先选择的对象来代替上下文变量容器来执行,被选择的对象使用th:object标签来指定:

name:Alice

name:Alice

在不考虑上下文的情况下,${...}*{...}两者没有区别,唯一区别在于使用*{...}前可以在父标签中通过th:object预先指定一个对象代替上下文变量容器:

... ... ...

链接表达式@{}

链接表达式@{...}用于页面跳转或者资源的引入,一般用于替换 href 标签中的链接 URL 地址,例如:



Default URL

Default URL

Default URL

除此之外,链接表达式也可以读取变量值进行动态拼接 URL 地址:


Default URL
Default URL
Default URL

如果链接的 URL 地址用多个参数,可以自行拼接字符串,还是使用逗号隔开,写法如下:


Default URL

分段表达式~{}

分段表达式~{}用于将标记片段移动到模板,一般使用th:insertth:replace引用片段。

基本使用

? 标记片段



标记片段

? 引用片段



最终生成代码如下:



aaa
aaa

分段表达式传参

分段表达式~{}可以传递参数,根据传递参数的不同显示不同的样式,例如:






条件逻辑判断

?? 条件表达式




    
    Thymeleaf Test


    
    

当前的用户为:Admin

当前的用户为:Admin

当前的用户为:Admin

当前的用户为:Admin

@Controller
public class ThymeleafController {

    @GetMapping("/hello")
    public String hello() {
        return "test";
    }
}

访问localhost:8080/hello,网页显示:

?? 条件语句

th:if 和 th:unless

Thymeleaf 使用th:ifth:unless进行条件判断,HTML5 标签中的内容只有th:if的表达式条件为 true 时才显示,th:unlessth:if恰好相反,只有表达式条件为 false 时才显示 HTML5 标签中的内容。




    
    Thymeleaf Test


    
th:if 条件判断

当前的用户为:Default Text.

th:unless 条件判断

当前的用户为:Default Text.

@Controller
public class ThymeleafController {

    @GetMapping("/hello")
    public String hello(Model model) {
        Person person = new Person();
        person.setName("Alice");
        model.addAttribute("person", person);
        return "test";
    }
}

访问localhost:8080/hello,网页显示:

`th:if`的表达式判断规则如下:
  • 如果表达式值为 null,直接返回 true;

  • 如果表达式值不为 null,以下情况返回 true:

    • 表达式值为 boolean 类型,并且为 true;
    • 表达式值是数值类型,并且不为零;
    • 表达式值是字符类型,并且不为零;
    • 表达式值是 String 类型,并且不是 “false” “off” 或 “no”;
    • 表达式值不是 boolean、数值、字符、String 类型的其他类型。

th:unless的表达式判断规则和th:if相反。

th:switch

Thymeleaf 支持多路选择 Switch 结构,类似于 Java 的swith...case...default,只不过默认属性 default 用 * 表示,使用如下:




    
    Thymeleaf Test


    
    

User is an administrator

User is an manager

User is some other thing

@Controller
public class ThymeleafController {

    @GetMapping("/hello")
    public String hello(Model model) {
        model.addAttribute("role", "manager");
        return "test";
    }
}

访问localhost:8080/hello,网页显示:


循环迭代访问

?? 基本迭代




    
    Thymeleaf Test


姓名 年龄
public class Person {
    private String name;
    private Integer age;

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    // getter 和 setter 方法略写
}
@Controller
public class ThymeleafController {

    @GetMapping("/hello")
    public String hello(Model model) {
        List persons = new ArrayList<>();
        persons.add(new Person("张三", 10));
        persons.add(new Person("李四", 20));
        persons.add(new Person("王五", 30));
        persons.add(new Person("赵六", 40));
        model.addAttribute("persons", persons);
        return "test";
    }
}

访问localhost:8080/hello,网页显示:

?? 状态变量

th:each除了循环迭代元素基本使用外,还可以设置状态变量来跟踪迭代器的状态,状态变量有如下属性:

  • index:当前迭代元素的索引,从 0 开始
  • count:当前迭代元素的索引,从 1 开始
  • size:当前迭代集合中元素的总数
  • current:当前的迭代元素对象
  • even/odd:布尔值,判断当前迭代元素的索引是否为偶/奇数(从1开始索引)
  • first:布尔值,判断当前迭代元素是否为第一个
  • last:布尔值,判断当前迭代元素是否为最后一个



    
    Thymeleaf Test
    


index count 姓名 年龄
@Controller
public class ThymeleafController {

    @GetMapping("/hello")
    public String hello(Model model) {
        List persons = new ArrayList<>();
        persons.add(new Person("张三", 10));
        persons.add(new Person("李四", 20));
        persons.add(new Person("王五", 30));
        persons.add(new Person("赵六", 40));
        model.addAttribute("persons", persons);
        return "test";
    }
}

访问localhost:8080/hello,网页显示:


参考

  1. Thymeleaf 语法详解及编码实践
  2. Thymeleaf 内置工具