文章目录
一,Thymeleaf介绍
Web动态页面的开发最早是使用JSP技术来开发,随着技术的更替,目前主流的技术方案是Thymeleaf。他是一个非常强大的框架模板,与HTML融合十分密切,也是SPring默认的模板方案。
1.何为模板
我们有如下一个歌曲属性:
{
"id":"1",
"name":"成都"
}
我们通过一定手段将参数传入模板,再在模板中接受:
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<h1 th:text="${songList.name}"></h1>
</body>
</html>
之后模版会将其渲染成普通的HTML页面:
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<h1>成都</h1>
</body>
</html>
如上,我们通过模板引擎,可以把Java对象中的数据和模板页面合并,渲染出一个真实的html页面来。如果之后name的名称改变,渲染的页面也会跟着改变。
2.初始化Thymeleaf
- 添加依赖
首先添加Maven依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
- 传递数据
导入依赖之后便可以向模板传递数据。SpringMVC对页面数据层的封装非常完善,因此我们只需要在方法中引入一个model对象,然后调用model的相应方法就能将参数传入到页面中去。
Model的全类名为:
import org.springframework.ui.Model;
我们尝试着传入一个歌单对象:
@Controller
public class SongListControl {
//此歌单数据和上面的成都对应
@Autowired
private SongListService songListService;
@RequestMapping("/songlist")
public String index(@RequestParam("id")String id,Model model){
SongList songList = songListService.get(id);
//传递歌单对象到模板当中
//第一个 songList 是模板中使用的变量名
// 第二个 songList 是当前的对象实例
model.addAttribute("songList",songList);
return "songList";
}
}
- 模板文件
SpringMVC中对于模板文件是有固定的存放位置的,为工程的src/main/resources/templates
目录。
因此,我们写的 return "songList"
会自动查找src/main/resources/templates/songList.html
文件,后缀名系统会自动匹配,也无需写成return "songList.html"
。
songList文件格式如下:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://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" />
<link rel="stylesheet" href="/css/songList.css" />
<title>歌单</title>
</head>
<body>
<h1 th:text="${songList.name}"></h1>
</body>
</html>
注意:
- 虽然此文件后缀也是html,且大部分内容跟html文件很像,但是因为他放置在
src/main/resources/templates
目录下,且含有变量th:text="${...}"
,所以其实他不是html文件,而是Thymeleaf模板。html静态文件放在src/main/resources/static
目录下。xmlns:th="http://www.thymeleaf.org
的作用是,在写代码时,让软件识别Thymeleaf语法。- 只要在工程的
src/main/resources/templates
目录下放置了文件,就表示需要用到Thymeleaf,这些文件就是模板,因此必须在pom.xml中导入依赖。
二,Thymeleaf变量
Thymeleaf 模板语法非常强大,相当于是一门动态编程语言,所以很多语言的特性它都支持,比如说变量、循环、条件等,在我们上节中使用的 th:text="${...}"
就是使用变量技术。
1.模板变量
由于 Thymeleaf 是完全兼容 HTML 的,所以为了不破坏 HTML 结构,Thymeleaf 采用了自定义 HTML 属性的方式来生成动态内容。
th:text
这个属性就是 Thymeleaf 自定义的 HTML 标签属性,th为Thymeleaf缩写,作用就是替换掉html标签的内部内容。例如:
<span th:text="${hello}">HelloWorld</span>
这段代码的含义就是用hello的参数值替换span标签中的内容。加入标签里面的内容是萨瓦迪卡,那么这句话的渲染结果就是:
<span>萨瓦迪卡</span>
${hello}
即为读取变量。如果我们想要获得变量,就需要先将变量设置到模板上下文中去,即在Controller中使用model.addAttribute("hello","萨瓦迪卡")
方法来设置变量。
第一个参数设置的就是上下文变量名(变量名是可以随便定义),第二参数设置的是变量值(可以是任意的对象)。
2.对象变量
模板语言还可以支持对象的输出,我们可以调用参数的属性,像我们需要的内容调用出来。
我们给songList添加一些内容:
import org.springframework.ui.Model;
@Controller
public class DemoControl {
@RequestMapping("/demo")
public String index(Model model){
SongList songList = new SongList();
songList.setId("0001");
songList.setName("爱你一万年");
model.addAttribute("sl",songList);
return "demo";
}
}
之后便可以在模板中通过th:text="sl.name"
,th:text="sl.id"
分别获取到name和id的值。
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8" />
</head>
<body>
<span th:text="${sl.id}"></span>
<span th:text="${sl.name}"></span>
</body>
</html>
注:对象只要是POJO类,即可通过该方法调用对象中的对象,和Java语法类似。
三,Thymeleaf循环语句
1.遍历打印元素属性
和Java相似,Thymeleaf也可以实现标签属性的循环,th:each
代表的就是循环语句。
<ul th:each="song : ${songs}">
<li th:text="${song.name}">歌曲名称</li>
</ul>
- ${songs}是从模版上下文中获取的变量;
- song是songs变量遍历后的每一个对象;
- ${song.name}就可以获取遍历中的歌曲名称了。
我们继续添加对象内容:
@RequestMapping("/demo")
public String index(Model model){
List<Song> songs = new ArrayList<>();
Song song = new Song();
song.setId("0001");
song.setName("朋友");
songs.add(song);
song = new Song();
song.setId("0002");
song.setName("夜空中最亮的星");
songs.add(song);
model.addAttribute("songs",songs);
return "demo";
}
通过上面的语句便可以将两个名字循环打印在页面中。
Thymeleaf 支持各种数据类型,如 List ,还可以支持数组、Map,你可以当成 Java 的 for 语句一样,集合类都可以支持
2.打印表的索引值
我们经常看到有些列表需要显示当前行数,这个时候,就需要借助 th:each
语句的另一种写法:
<ul th:each="song,it: ${songs}">
<li>
<span th:text="${it.count}"></span>
<span th:text="${song.name}"></span>
</li>
</ul>
运行后结果如下:
- 1朋友
- 2夜空中最亮的星
这段代码中多了一个it参数,如果定义了就可以通过这个it对象来获取更多的统计需求,具体参数如下:
-
it.index
当前迭代对象的 index(从 0 开始计算),如果想从 0 开始显示行数用这个就可以了
-
it.count
当前迭代对象的 index(从 1 开始计算),如果显示行数用这个就可以了
-
it.size
被迭代对象的大小,如果想获取列表长度,用这个就可以了
-
it.current
当前迭代变量,等同与上面的 song
-
it.even/odd
布尔值,当前循环是否是偶数/奇数(从 0 开始计算)
-
it.first
布尔值,当前循环是否是第一个
-
it.last
布尔值,当前循环是否是最后一个
模板中的布尔值需要结合条件语句来处理的
上面我们显示的都是单层的循环,如果你的数据对象是有多级的,也可以嵌套循环。
四,Thymeleaf表达式
Thymeleaf表达式主要有两种场景:
- 字符串处理
- 数据转化
1.字符串处理
类似于视频的计时显示00:00/45:00
,大家应该很容易明白这个代表的就是这个视频从 0 分 0 秒开始,总共 45 分钟。在 Thymeleaf 中这种显示就需要借助+
完成字符拼接:
<span th:text="'00:00/'+${totalTime}"></span>
注意需要使用’ ‘包裹住字符
00:00/
否则会报错
字符串拼接优化
可以使用||包裹代码,这样就可以避免使用’…‘+’…’
<span th:text="|00:00/${totalTime}|"></span>
2.数据转化
Thymeleaf 默认集成了大量的工具类可以方便的进行数据转化,一般我们使用最多的是dates。
如果想要处理LocalDate
和LocalDateTime
类,可以在pom.xml中添加如下依赖:
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
<version>3.0.4.RELEASE</version>
</dependency>
该库会自动添加一个temporals工具类。
工具类的运用和变量不同,变量的使用是${变量名},工具类的使用是#{工具类}。具体运用如下:
dates/temporals
二者支持的方式是一样的,只是支持的类型不同,dates支持的是Date类,temporals支持的是LocalDate和LocalDateTime类。
java.util.Date 类和 LocalDateTime 类功能是一样的,不同的是 LocalDateTime 是 Java8 才出现的,一些老的应用还是用 Date 类的。
我们一般使用dates/temporals用于处理日期类型到字符串的转化,比如显示年月日:
<p th:text="${#dates.format(dateVar, 'yyyy-MM-dd')}"></p>
<p th:text="${#dates.format(dateVar, 'yyyy年MM月dd日')}"></p>
或者年月日时分秒:
<p th:text="${#dates.format(dateVar, 'yyyy-MM-dd HH:mm:ss')}"></p>
<p th:text="${#dates.format(dateVar, 'yyyy年MM月dd日 HH时mm分ss秒')}"></p>
java代码如下:
@RequestMapping("/demo")
public String index(Model model){
Date dateVar = new Date();
model.addAttribute("dateVar",dateVar);
return "demo";
}
如果类型是LocalDate/LocalDateTime那么就把
#dates换成
#temporals
@RequestMapping("/demo")
public String index(Model model){
LocalDateTime dateVar = LocalDateTime.now();
model.addAttribute("dateVar",dateVar);
return "demo";
}
String
除了日期以外,#string也是使用较多的,支持字符串的数据处理,如:
#strings
也是我们使用比较多的,支持字符串的数据处理,比如
-
${#strings.toUpperCase(name)}
把字符串改成全大写
-
${#strings.toLowerCase(name)}
把字符串改成全小写
-
${#strings.arrayJoin(array,',')}
把字符串数组合并成一个字符串,并以
,
连接,比如["a","b"]
执行后会变成a,b
-
${#strings.arraySplit(str,',')}
把字符串分隔成一个数组,并以
,
作为分隔符,比如a,b
执行后会变成["a","b"]
;如果abc
没有匹配到,执行后会变成["abc"]
-
${#strings.trim(str)}
把字符串去空格,左右空格都会去掉
-
${#strings.length(str)}
得到字符串的长度,也支持获取集合类的长度
-
${#strings.equals(str1,str2)}
比较两个字符串是否相等
-
${#strings.equalsIgnoreCase(str1,str2)}
忽略大小写后比较两个字符串是否相等
这些函数可以尝试去练习一下,基本上这些多做一些产品开发就非常熟练了
完整的内置对象,大家了解就可以了,用到的时候自己查查文档。
内联表达式
th:text
还有一种更简便的写法,就是将变量写在html里面,如:
<span>Hello [[${msg}]]</span>
只需要在java代码中传入参数:
@RequestMapping("/demo")
public String index(Model model){
String msg = "丫丫";
model.addAttribute("msg",msg);
return "demo";
}
用内联表达式执行日期函数:
<p>[[ ${#dates.format(dateVar, 'yyyy-MM-dd')} ]]</p>
<p>[[${#dates.format(dateVar, 'yyyy年MM月dd日')}]]</p>
<p>[[${#dates.format(dateVar, 'yyyy-MM-dd HH:mm:ss')}]]</p>
<p>[[${#dates.format(dateVar, 'yyyy年MM月dd日 HH时mm分ss秒')}]]</p>
五、Thymeleaf条件语句
语法为th:if
,当if表达式的值为true的情况下就会执行渲染
<span th:if="${user.sex == 'male'}">男</span>
或者使用th:unless
,表示否定条件,和if相反。
<span th:unless="${user.sex == 'male'}">女</span>
Java代码如下:
@RequestMapping("/demo")
public String index(Model model){
User user = new User();
user.setId("0001");
user.setName("范闲");
user.setSex("male");
model.addAttribute("user",user);
return "demo";
}
除了boolean值以外,Thymeleaf还认为一下表达式为true:
- 值非空
- 值是非零数字
- 值是字符串,但不是false,off或者no
- 值不是boolean值,数字,character或者字符串
String逻辑判断
在很多时候,我们还会借助#string
这个内置对象来做逻辑判断和数据处理,比如isEmpty
检查变量是否为空或null:
${#strings.isEmpty(name)}
//数组
${#strings.arrayIsEmpty(name)}
//集合
${#strings.listIsEmpty(name)}
测试一下:
@RequestMapping("/demo")
public String index(Model model){
String str1 = "a";
String str2 = "";
String str3 = " ";
String str4 = null;
model.addAttribute("str1",str1);
model.addAttribute("str2",str2);
model.addAttribute("str3",str3);
model.addAttribute("str4",str4);
return "demo";
}
模板代码如下:
<p th:if="${#strings.isEmpty(str1)}">String str1 = "a";</p>
<p th:if="${#strings.isEmpty(str2)}">String str2 = "";</p>
<p th:if="${#strings.isEmpty(str3)}">String str3 = " ";</p>
<p th:if="${#strings.isEmpty(str4)}">String str4 = null;</p>
运行结果只有String str1 = “a“没有显示出来,其他几种都匹配为true
contains
检查字符串是否包含片段
${#strings.contains(name,'abc')}
除此之外还有其他几种常用的判断:
-
${#strings.containsIgnoreCase(name,'abc')}
先忽略大小写字母,然后去判断是否包含指定的字符串
-
${#strings.startsWith(name,'abc')}
判断字符串是不是以 abc 开头的
-
${#strings.endsWith(name,'abc')}
判断字符串是不是以 abc 结束的
#strings 的字符串操作函数
除了字符串判断语句外,#strings 还支持字符串的数据处理,比如
-
${#strings.toUpperCase(name)}
把字符串改成全大写
-
${#strings.toLowerCase(name)}
把字符串改成全小写
-
${#strings.arrayJoin(array,',')}
把字符串数组合并成一个字符串,并以
,
连接,比如["a","b"]
执行后会变成a,b
-
${#strings.arraySplit(str,',')}
把字符串分隔成一个数组,并以
,
作为分隔符,比如a,b
执行后会变成["a","b"]
;如果abc
没有匹配到,执行后会变成["abc"]
-
${#strings.trim(str)}
把字符串去空格,左右空格都会去掉
-
${#strings.length(str)}
得到字符串的长度,也支持获取集合类的长度
-
${#strings.equals(str1,str2)}
比较两个字符串是否相等
-
${#strings.equalsIgnoreCase(str1,str2)}
忽略大小写后比较两个字符串是否相等