梦入琼楼寒有月,行过石树冻无烟

Spring boot and Thymeleaf 变量表达式

标准变量表达式语法

ID DA FA
${……} 变量表达式 变量表达式
*{……} 选择变量表达式
#{……} 信息表达式
@{……} 链接URL表达式
~{……} 片段表达式

在此我们只线上简单表达式的语法,还有一些Thymeleaf的语法我相信读者都是学过html、css、js这些的都可以大致看懂,所以本书也没必要将重点列在表达式语法之中,在此基础上学习和认知、了解到简单表达式就差不多了。

标签

ID DA
th:id 替换id
th:text 文本替换
th:utext 不可被替换的文本
th:object 替换对象
th:value 替换值
th:each 迭代
th:href 替换超链接
th:src 资源替换

Thymeleaf ${……}

Thymeleaf ${……}的主要作用是变量表达式,通常我们需要另建一个Java文件在spring boot web项目之中,然后html页面通过${……}来获取.Java文件的内容。有一个有趣的故事是单个打开html和在服务器端显示的不同,这里的不同主要是html不懂Thymeleaf语法,于是就输出了${……}之后标签内的语法如:<p th:text="${name}">Go html</p>在服务器端会输出.Java文件内name相应的数据内容,而在html环境下由于html也不懂Thymeleaf语法干脆忽略掉了而输出Go html

application.properties
1
2
spring.thymeleaf.cache=false
spring.thymeleaf.encoding=UTF-8
urlController.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class urlController {
@GetMapping("index")
public String getindex(Model model) {
model.addAttribute("name","Thymeleaf");
return "index";
}
}
index.html
1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body>
Thymeleaf one html
<p th:text="${name}">Go html</p>
</body>
</html>

需要值得注意的是在urlController中所属的包是由spring boot项目构建时自动生成的包,直接在com.example.demo包下新建类即可,而index.html文件是存放于src/main/resources/templates之中的,在application.properties内的配置分别为自动清除Thymeleaf缓存,即不需要重启Spring boot来刷新数据,理论上是如thymeleaf改变服务端也随即改变,这个改变是不包括css/js的。

${……[]}

在Spring boot与Thymeleaf搭配的项目之中,可以使用bash方法编写一个类似于列表数据的方法,及通过java建立对象,html使用${……[]}的方法引入java对象数据即:

data.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.example.demo;

public class data {
private String name;
private int age;

public data(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
}
urlController.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class urlController {
@GetMapping("index")
public String getindex(Model model) {
data dataone = new data("username",20);
model.addAttribute("namedata",dataone);
return "index";
}
}
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Home</title>
<link th:href="@{/css/style.css}" href="../static/css/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<h5>Java Bean object</h5>
<table>
<tr>
<td>Name:</td>
<td th:text="${namedata.name}">namedata</td>
</tr>
<tr>
<td>Age:</td>
<td th:text="${namedata.age}">agedata</td>
</tr>
</table>
</body>
</html>

Thymeleaf @{……}

本文的@{……}由于使用本地环境导致spring boot无法找到style.css,这个问题其实主要的原因是环境的不同,在spring boot是自动配置、自动寻找的,所以不要使用绝对目录如:

1
2
3
4
5
6
7
8
9
10
11
12
 <!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Home</title>
<link th:href="@{../static/css/style.css}" href="../static/css/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
Thymeleaf one html
<p th:text="${name}">Go html</p>
</body>
</html>
index.html
1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Home</title>
<link th:href="@{/css/style.css}" href="../static/css/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
Thymeleaf one html
<p th:text="${name}">Go html</p>
</body>
</html>
style.css
1
2
3
4
# resources/static/css/
p {
color: red;
}

你会发现直接点击html并浏览时css是正常运行的,而正到服务器端访问时就出现大问题了,就是访问不到style.css,返回结果404。这时我们将th:href="@{../static/css/style.css"更改为th:href="@{/css/style.css}即可,这样即保证了服务端的正常渲染也保证了静态调试的时候正常渲染。

th:href @{……}

本次我们使用 th:href 标签来实现 @{……}方法,通常我们在生产环境之中都需要用到相对路径即 https://pv.zsun.org.cn/about,而不是绝对路径https://pv.zsun.org.cn/login.php,这样不仅仅链接不美观还存在着一些```安全风险```,在互联网中有一群打着“白帽子”的脚本小子通常最喜欢这种使用绝对路径的站点了,他们会不择手段的对你的站点进行测试,这种感觉也非常无语,所以本章通过 th:href来实现相对目录。

1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Home</title>
<link th:href="@{/css/style.css}" href="../static/css/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<h5>Java Thymeleaf href</h5>
<hr />
<a href="insert.html" th:href="@{insert}">Go insert</a>
</body>
</html>

这样写的好处是不仅仅是为了安全性考虑,且在本地测试中不会在对服务器应用进行设置,无需另开发对生产环境的程序或工作,一次开发,兼顾了本地测试和生产环境,这也是Thymeleaf的特点之一。

Thymeleaf *{……} & ${……}

在Thymeleaf标准表达式语法之中,可使用*{……}${……}互相进行搭配,其中可更方便的运用在列表之中,而实现过程与Thymeleaf中的 ${……[]}相差无几,只是多了个*{……}让其更加方便的编写:

data.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.example.demo;

public class data {
private String name;
private int age;

public data(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
}
urlController.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class urlController {
@GetMapping("index")
public String getindex(Model model) {
data dataone = new data("username",20);
model.addAttribute("name","Thymeleaf");
model.addAttribute("namedata",dataone);
return "index";
}
}
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Home</title>
<link th:href="@{/css/style.css}" href="../static/css/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<h5>Java Bean object</h5>
<table th:object="${namedata}">
<tr>
<td>Name:</td>
<td th:text="*{name}">namedata</td>
</tr>
<tr>
<td>Age:</td>
<td th:text="*{age}">agedata</td>
</tr>
</table>
</body>
</html>

Thymeleaf #{……}

与上面的一些表达式语法相比,基本上都是通过读取Controller控制器值来读取信息的,而相比之下 #{……}就显得平淡无奇且低调奢华了,这个表达式虽然并不常用但却比通过读取Controller值方便许多,因为他本身就是用于读取配置内的信息的(这里的配置仅单指.properties)Springboot配置文件。

application.properties
1
2
3
spring.thymeleaf.cache=false
spring.thymeleaf.encoding=UTF-8
spring.messages.basename=templates/data

application 主要用于指定创建好的.properties文件,之后Thymeleaf #{……}通过读取.properties配置文件信息来显示输出,如不再spring boot全局配置文件中配置则会显示 ??language_zh_CN??,所以需要指定其.properties目录和文件名

data.properties
1
2
data.name=kunlunsiqu
data.age=22
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Home</title>
<link th:href="@{/css/style.css}" href="../static/css/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<h5>Java Bean object</h5>
<table>
<tr>
<td>Name:</td>
<td th:text="#{data.name}">namedata</td>
</tr>
<tr>
<td>Age:</td>
<td th:text="#{data.age}">agedata</td>
</tr>
</table>
</body>
</html>

Thymeleaf ~{……}

Thymeleaf {……}片段表达式通过th:insert标签分别分为两步为分别为定义和引入两种方式,可以理解为一个页面中的数据通过片段表达式可供多个页面进行引用,其格式为```th:insert=”{文件名 :: 片段名}```”如本书例子;

定义
insert.html
1
2
3
4
5
6
7
8
9
10
11
12
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert</title>
</head>
<body>
<div th:fragment="data">
2020-01-05 19:48:34 Jiangxue & ZhongShan
</div>
</body>
</html>
引入
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Home</title>
<link th:href="@{/css/style.css}" href="../static/css/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<h5>Java Insert</h5>
<hr />
<div th:insert="~{insert :: data}"></div>
</body>
</html>
⬅️ Go back