Spring Boot 【2】 使用 Thymeleaf 模板引擎

现在网站大致就是两种方案,服务器端渲染HTML或者单页面应用+API的方式。

服务器端渲染以前有 JSP 这样的方案,但由于 JSP 中要夹杂很多的 Java 代码,和前端开发一起工作的时候会前端可能会看不懂 JSP 的页面,不知道哪些部分可以修改。而使用 Thymeleaf 来进行开发的话,它的语法就和现在的前端框架很接近。而且 Thymeleaf 的 HTML 文件脱离了我们 Java 后端的数据,依然可以在浏览器中看到页面的效果,对前端开发比较友好。

当然,如果写习惯了 JSP,也没有使用过一些常见的前端框架的话,可能就对 Thymeleaf 的语法比较陌生了。

 

开始使用

我们这个项目是 Maven 构建的,所以先在 pom.xml 中添加所需要的依赖。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

 

保存之后,IntelliJ 会提示我们是否导入我们添加的依赖,点击 Enable Auto-Import ,以后我们修改了 pom.xml 中的依赖它就会自动开始下载了。

打开 resources 下的 application.properties ,在里面添加一行

spring.thymeleaf.cache=false

这样子可以关闭掉 Thymeleaf 的缓存,target 中的文件改变之后不需要重启 Spring Boot 应用(Tomcat)就可以刷新看到变化。

 

打开之前创建的 HomeController ,然后我们把 index 方法改成这样

@GetMapping("/")
public String index(Model model) {
    model.addAttribute("message", "Hello Thymeleaf");
    return "index";
}

接下来我们要在 resources 目录的 templates 下创建一个 index.html

 

index.html 的内容如下

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
    <meta charset="UTF-8">
    <title th:text="${message}"></title>
</head>
<body>
<h3 th:text="${message}">

</h3>
</body>
</html>

 

此时我们重新运行一下,打开 http://localhost:8080/

页面中显示出了Hello Thymeleaf

解释

回到 HomeController 中,我们给 index 方法添加了一个 Model 参数,通过这个参数,可以给 Thymeleaf 页面传值。

这个类中是以 key-value 方式存储的,给它传值的方法如下:

model.addAttribute(String, Object)

这个值可以是 String 、Collection 等各种类。

然后这里的返回值我们写的是 “index”,他会在 templates 下寻找 index.html 文件,在这里我们不需要添加 .html 的后缀名。

 

接下来我们看一下 index.html。

首先在 html 标签中添加了一个 xmlns:th=”http://www.thymeleaf.org” 的命名空间。

Thymeleaf 的标签都是 th 开头的,这里使用了 th:text 属性,th:text 会改变这个html标签中的值。

${message} 代表的是我们在 model 中添加的键为 message 的数据。

所以 <h3 th:text=”${message}”></h3> 将会渲染出 <h3>Hello Thymeleaf</h3>

 

展示对象中的内容

我们可以创建一个 Person 类,他有 id、 name、 age 三个属性。

public class Person {

    private long id;

    private String name;

    private int age;

    public Person() {
    }

    public Person(long id, String name, int age) {
        this.id = id;
        this.name = name;
        this.age = age;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

 

接下来在 HomeController 中再添加一个页面

@GetMapping("/person")
public String person(Model model) {
    Person person = new Person(1,"David", 25);
    model.addAttribute("person",person);
    return "person";
}

这里创建了一个 Person 对象,然后把它传给了 model

 

接下来我们创建一个 person.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
    <meta charset="UTF-8">
    <title>Person</title>
</head>
<body>
<p>
    ID: <span th:text="${person.id}"></span><br>
    Name: <span th:text="${person.name}"></span><br>
    Age: <span th:text="${person.age}"></span><br>
</p>
</body>
</html>

看到代码应该就懂了,我们可以通过 person.<属性> 获取到 person 对象的各种值。

浏览器中运行的效果:

 

展示 List 中的内容

我们再添加一个页面

@GetMapping("/personList")
public String personList(Model model) {
    List<Person> personList = new ArrayList<>();
    personList.add(new Person(1,"David", 25));
    personList.add(new Person(2,"Kevin", 30));
    personList.add(new Person(3,"Jenny", 23));
    
    model.addAttribute("personList", personList);
    return "personList";
}

在 personList 中添加了三个 Person 对象,然后传给 model

 

personList.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
<head>
    <meta charset="UTF-8">
    <title>Person List</title>
</head>
<body>
<p th:each="person : ${personList}">
    ID: <span th:text="${person.id}"></span><br>
    Name: <span th:text="${person.name}"></span><br>
    Age: <span th:text="${person.age}"></span><br>
</p>
</body>
</html>

这里使用了一个 th:each 的属性。其实使用方法就相当于 forEach 循环。

 

可以看到它把 List 中的内容都展示出来了。