Springboot与Thymeleaf

830 阅读2分钟

准备

  1. 从Maven引入
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
  1. application.yml/properties配置 实际上org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties已经有默认的配置项,例如:
private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";

所以可以直接使用,暂时不用关心ThymeleafProperties中的配置。

  1. html文件位置及命名空间

  2. 要使用Thymeleaf功能的html文件,都得放到如下所示templates目录下,刚才已经提到了Thymeleaf的一些默认配置,所以,也没必要去改变DEFAULT_PREFIX

// org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties
public static final String DEFAULT_PREFIX = "classpath:/templates/";
+---main
|   +---java
|   |   \---com
|   |       \---xxx 包
|   \---resources
|       +---static
|       \---templates
  1. html文件的html 标签引入xmlns:th命名空间,防止IDE报错缺少名称空间定义,同时也有了提示,比如使用 IDEA .
<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge,chrome=1">
    <title>Document</title>
</head>

先了解一下简单的表达式

  • 简单表达式
    • 变量表达式: ${...}
    • 选择变量表达式: *{...}
    • 消息表达: #{...}
    • 链接URL表达式: @{...}
    • 片段表达式: ~{...}

以下使用org.springframework.ui.Model来传递数据

文本

标签本身没有value属性的,如p li span等用th:text渲染,有value属性则用th:value渲染

判断

@GetMapping("judge")
public String books(Model model) {
    model.addAttribute("param", "xxx");
    return "/books";
}
<!-- 使用 th:if -->
<div th:if="${param}">
 ...
</div>

当是变量是以下情况时th:if判断为false,从而不渲染元素

  1. 变量不存在
  2. 值为null
  3. 值为Boolean类型的false

循环

  1. 简单循环
@GetMapping("books")
public String books(Model model) {
    List<String> list = Arrays.asList("陸小鳳傳奇", "蘇菲的世界", "毛澤東選集");
    model.addAttribute("books", list);
    return "/books";
}
<ul>
    <li th:each="book :${books}">
        <span th:text="${book}"></span>
    </li>
</ul>
  1. 对象集合
@Getter
@Setter
@AllArgsConstructor
public class UserObj {
    private Integer id;
    private String name;
    private Integer age;
}

@GetMapping("users")
public String users(Model model) {
    UserObj lily = new UserObj(1, "Lily", 22);
    UserObj jasmine = new UserObj(2, "Jasmine", 18);
    UserObj poppy = new UserObj(3, "Poppy", 6);
    List<UserObj> list = Arrays.asList(lily, jasmine, poppy);
    // model.addAllAttributes(list);
    model.addAttribute("users", list);
    return "/user";
}
<table th:if="${users}">
    <thead>
    <tr>
        <th>ID</th>
        <th>NAME</th>
        <th>AGE</th>
    </tr>
    </thead>
    <tbody>
    <tr th:each="user,iterStat :${users}" th:class="${iterStat.odd}? 'odd'">
        <td th:text="${user.id}"></td>
        <td th:text="${user.name}"></td>
        <td th:text="${user.age}"></td>
    </tr>
    </tbody>
</table>

第二个参数 iterStat 是一个对象,是为Thymeleaf提供了一种有助于跟踪迭代状态的机制,其拥有以下属性:

{
    index: 0 索引 从零开始, 
    count:  从一开始的索引, 
    size:   数据总数, 
    current:com.xxx.UserObj@7684eac 当前循环的对象,
    even/odd:布尔属性,当前迭代是偶数还是奇数
    first: 布尔属性 是否是第一个   
    last:   布尔属性 是否为最后一个 
}

注释

<!-- 普通html注释 -->

<!--/* 被Thymeleaf解析后不显示 */-->

<!--/*/
  <div th:text="${...}">
    静态打开时不显示,被Thymeleaf解析后显示
  </div>
/*/-->

模板

例如页脚,页眉,菜单等部分做成模板以嵌入到其它页面中。

制作

例如制作一个header模板,在/layout目录下新建一个header.html,文件内容如下所示,因为这只是一个嵌入到其它html的片段,所以不再写<!DOCTYPE html>和其它用不到的标签。

<header xmlns:th="https://www.thymeleaf.org" th:fragment="header">
...
</header>
或者 使用id来声明
<header xmlns:th="https://www.thymeleaf.org" id="header">
...
</header>

使用

<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org">
<head>
   ...
</head>
<body>
    <div th:replace="~{/layout/header :: header}"></div>
    <!-- 如果使用id声明,则加个#号 -->
    <div th:replace="~{/layout/header :: #header}"></div>
</body>
</html>

差异

th:insert th:replaceth:include之间的差异

3.0 不推荐th:replace

以上面的使用为例

  1. th:insert 最简单:它将简单地将指定的片段作为子标签插入,即
<div>
    <header>
     ...
    </header>
</div>
  1. th:replace实际上将其标签替换为引用的片段,,即
<header>
 ...
</header>
  1. th:include与相似th:insert,但不插入片段,而是仅插入该片段的内容,即
<div>
 ...
</div>

附录

表达式基本对象

expression-basic-objects

未完待续?