十分钟一篇给你讲清楚 Spring Thymeleaf 模版框架(更适合新手宝宝体质)

这一篇是干货中的干货,建议大家点赞收藏,适合学完一遍再多敲敲,有需要就回来查

Thymeleaf 入门

Web 开发离不开动态页面的开发,很早以前企业主要使用JSP技术来开发网页,随着技术的升级更替,目前来说最主流的方案是Thymeleaf,Thymeleaf 是一个模板框架,它可以支持多种格式的内容动态渲染非常强大,它天然和 HTML是相融合的,所以对于前端工程师来说它也是易于理解的。

还有一个重要的原因是 Spring 选择 Thymeleaf 作为默认模板方案,Spring 的选择自然让这项技术成为最优先采用的方案啦

Web 工程师基本上也必须要掌握一门模板框架的,要不然没有办法完成动态网页的开发工作,这也是软件开发最基本的要求了

模版:

在这里插入图片描述

如上图,我们通过模板引擎,可以把 Java 对象数据+模板页面动态的渲染出一个真实的 HTML 页面来。

上面的例子中,如果 name 变成其他歌单的名称,那么页面染后也自然就会变成新的歌单名称

模板引擎在所有的 Web 编程语言里都有类似的方案的,所以大家掌握住一个框架,以后在去学习其他的也很容易。关键先理解它的机制,简单的来说就是 数据+模板+引擎 渲染出真实的页面

如何初始化 Thymeleaf

添加 Maven 依赖

由于现代的工程都是基于 Spring Boot 来搭建的,所以我们使用Thymeleaf 也非常简单。我们只需要在工程的pom.xml中添加依赖即可

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

数据传递

Spring MVC 把页面数据层封装的非常完善,只需要我们在方法参数里引入一个 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";
  }
}

模板文件

Spring MVC 中对于模板文件是有固定的存放位置,放置在工程的src/main/resources/templates
所以上面的 return"songList";其实会去查找src/main/resources/templates/songList.html文件,系统会自动去匹配后缀的,所以你不需要写成return “songList.html";

Thymeleaf 模板文件也是以 html 作为文件格式的,所以它也是最容易学习的模板

最后我们的文件内容如下

<!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 模板

➤另外需要注意:xmlns:th="http://www.thymeleaf.org"的作用是,在写代码时,让软件能识别 thymeleaf 语法。

thymeleaf 变量、语法接下来会学习,这里不用太纠结

只要在工程的 src/main/resources/templates下面放置了文件,就表示需要使用 Thymeleaf ,这些文件就是 模板,无论在模板中是否写了变量(${songList.name})。这大家要注意理解规范。

放在src/main/resources/static目录下的就不是模板,是静态文件。

只要用到了 Thymeleaf 必须 \color{red}{必须} 必须 在工程的 pom.xml 文件中增上述依赖。忘记加了就会出错,而且可能不知道为什么出错,所以大家务必做到遵守规范,有问题先检查是否缺少依赖。

Thymeleaf 变量

搞定工程环境之后,我们就开始学习模板语法

Thymeleaf 模板语法非常强大,相当于是一门动态编程语言,所以很多语言的特性它都支持,比如说变量、循环、条件等

在我们上节中使用的 th:text="${songList.name}”这个就是使用变量技术

模板变量

由于 Thymeleaf 是完全兼容 HTML 的,所以为了不破坏 HTML 结构,Thymeleaf 采用了自定义 HTML 属性的方式来生成动态内容

th:text 这个属性就是 Thymeleaf 自定义的 HTML 标签属性, th是Thymeleaf 的缩写,所以你如果看到 th:开头的标签属性,那么就代表使用的是 是 Thymeleaf 语法

th:text语法的作用就是会动态替换掉 html 标签的内部内容,这句话啥意思呢?

<span th:text="${msg}">Hello</span>

这段代码的执行结果就是用 msg 变量值替换了 span 标签内的 Hello字符串,比如说 msg 变量值是 你好 ,那么代码渲染的结果是

<span>你好</span>

再来看看如何读取变量,上面th属性内的 ${msg}这个语法就是表示获取模板中的变量 msg,请注意这个语法格式(它是固定的)${xxx}

上下文这个术语在编程里用的比较多,一般泛指在某个具体的实例里,比如说模板上下文,指的是这个模板运行的实例

一般情况下,模板的变量都是会存放在模板上下文中,所以我们如果想要调用变量,就需要先设置变量到模板上下文中去,你只需要像上节课一样 model.addAttribute("songList",songList);就可以完成上下文变量的设置

比如,我们这个例子

import org.springframework.ui.Model;

@Controller
public class DemoControl {

  @RequestMapping("/demo")
  public String index(Model model){
    String str = "你好";
    model.addAttribute("msg",str);
    return "demo";
  }
}

大家仔细看看这个model.addAttribute("msg",str);这个方法

  • 第一个参数设置的就是上下文变量名(变量名是可以随便定义)
  • 第二参数设置的是变量值(可以是任意的对象)
对象变量

模板语言还可以支持复杂对象的输出,我们完全可以使用.把属性调用出来,比如我们的歌单对象 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 类哦

Thymeleaf 循环语句

在模板当中,for循环和变量的组合是最常见的,比如说歌单的歌曲列表,如果我们想显示出来,那就需要借助循环

Thymeleaf 的 for 循环也是使用标签属性来完成的,th:each 代表的就是循环语句

<ul th:each="song : ${songs}">
  <li th:text="${song.name}">歌曲名称</li>
</ul>

这段代码应该不难理解,基本上遵循的就是这样的语法

  • ${songs}是从模板上下文中获取 songs 这个变量song

  • song${songs} 变量遍历后的每一个对象

  • $​{song.name} 就可以读取遍历中歌曲名称了

我们在完善一下 Java 代码

  @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 语句一样,集合类都支持的

打印列表的索引值

我们经常看到有些列表需要显示当前行数,这个时候,就需要借助th:each语句的另外一种写法

<ul th:each="song,it: ${songs}">
  <li>
    <span th:text="${it.count}"></span>
    <span th:text="${song.name}"></span>
  </li>
</ul>

现在我们来看看上面的代码,大家仔细看看th:each="song,it:${songs}",你会发现多了一个,it 这个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 表达式对于动态数据处理更为方便

Thymeleaf 表达式主要用于两种场景

  • 字符串处理
  • 数据转化
字符串处理

我们在很多网站上都会看到视频时间的显示效果是这样的00:00/45:00,大家应该很容易明白这个代表的就是这个视频从0分0 秒开始,总共 45 分钟。在 Thymeleaf 中这种显示就需要借助+就可以完成字符串拼接了

<span th:text="'00:00/'+${totalTime}"></span>

这里需要注意的是'00:00/',我们使用 '包围住 00:00/这个文本的作用在于把这个文本变成 Java 字符串,两个字符串就可以使用 +拼接成新的字符串了,这和 Java 的字符串拼接是一样的。 Control 代码我们也调整一下

@RequestMapping("/demo")
  public String index(Model model){

    String totalTime = "45:00";

    model.addAttribute("totalTime",totalTime);
    return "demo";
  }

字符串拼接优化

Thymeleaf 做字符串拼接还做了优化工作,我们可以使用 上面的代码你还可以这样|包围住字符串,这样就不需要在文字后面附加

'...'+'...'

<span th:text="|00:00/${totalTime}|"></span>
数据转化

Thymeleaf 默认集成了大量的工具类可以方便的进行数据转化,一般我们使用最多的是 dates
如果你想处理 LocalDateLocalDateTime 类,你可以在 pom.xml添加如下依赖

<dependency>
  <groupId>org.thymeleaf.extras</groupId>
  <artifactId>thymeleaf-extras-java8time</artifactId>
  <version>3.0.4.RELEASE</version>
</dependency>

这个库会自动添加一个新的工具类temporals

工具类的运用和变量不同,变量使用的是${变量名},工具类使用的是 #{工具类}。我们依次看看具体如何运用

dates/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>
  @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

除了日期方法#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))

忽略大小写后比较两个字符串是否相等

这些函数大家自己可以尝试去练习一下,基本上这些多做一些产品开发就非常熟练了

完整的内置对象,大家了解就可以了,用到的时候自己查查文档,在具体的使用场景中我也会逐步介绍的,因为一下子我也记不住那
么多

#messages #urls/uris #conversions #dates#calendars#numbers #strings #objects #bools #arrays #lists #sets #maps #aggregates #ids

内联表达式

尽管我们使用 th:text 也比较方便,但是有些时候可能我们还是更喜欢直接把变量写在 HTML 中,比如这种写法
<span>Hello [[${msg}]]</span>
上面的 [[变量]]这种格式就是内联表达式,支持我们直接在 HTML中调用变量

  @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>

th:text[[]]两种写法都是允许的,每个团队可能规则不一样,我个人更喜欢使用 [[]],但是你要了解的是[[]]是用来替代th:text 的,不是替代所有的 th:标签哦

Thymeleaf 条件语句

动态页面必然会遇到 if/else 的情况,比如说网页中显示用户性别

  • user.sex 值是 male 则显示:男
  • user.sex 值是 female 则显示:女

Thymeleaf 也支持 if/else 能力,同样也是以 th:开头的属性,这次我们使用的是 th:if ,if 表达式的值是 ture 的情况下就会执行渲染

<span th:if="${user.sex == 'male'}"></span>

我们还可以使用 th:unless代表的是否定条件,这个语句和if 是相反的,代表的是 sex 不是 male 情况才会执行渲染

<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";
  }

th:if 条件判断除了判断 boolean 值外,Thymeleaf 还认为如下表达式为 true:

  • 值非空
  • 值是非0数字
  • 值是字符串,但不是falseoff or no
  • 值不是 boolean 值,数字,character 或 字符串.
用户列表

现在我们结合循环语句显示用户列表看看

<div>
  <li th:each="user : ${users}">
    <span>[[${user.name}]]</span>
    <span th:if="${user.sex == 'male'}"></span>
    <span th:unless="${user.sex == 'male'}"></span>
  </li>
</div>
 @RequestMapping("/demo")
  public String index(Model model){

    List<User> users = new ArrayList<>();

    User user = new User();
    user.setId("0001");
    user.setName("范闲");
    user.setSex("male");
    users.add(user);

    user = new User();
    user.setId("0002");
    user.setName("司理理");
    user.setSex("female");
    users.add(user);

    user = new User();
    user.setId("0003");
    user.setName("庆帝");
    user.setSex("male");
    users.add(user);

    user = new User();
    user.setId("0004");
    user.setName("海棠朵朵");
    user.setSex("female");
    users.add(user);

    model.addAttribute("users",users);
    return "demo";
  }
strings 逻辑判断

在很多时候,我们还会借助 #strings 这个内置对象来做逻辑判断和数据处理,比如

isEmpty

检查字符串变量是否为空(或者为 nul),在检查之前会先执行 trim()操作,去掉空格

${#strings.isEmpty(name)}

数组也适用 isEmpty

${#strings.arrayIsEmpty(name))

集会类也适用isEmpty

${#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>

运行完,大家应该看见页面只有 stringstr1=“a";没有显示出来,因为其他的几种都是匹配了 isEmpty=true

contains

检查字符串变量是否包含片段
${#strings.contains(name,'abc')}

现在我们可以测试一下

  @RequestMapping("/demo")
  public String index(Model model){
    String str1 = "我是中国人";
  
    model.addAttribute("str1",str1);
    return "demo";
  }

模版代码:

<p th:if="${#strings.contains(str1,'人')}">匹配到人这个字啦</p>

OK,我想你应该掌握到了这种用法了,#strings 判断语法还有几个常用的方法,大家可以自己测试一下

${#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)}

忽略大小写后比较两个字符串是否相等

这些函数大家自己可以尝试去练习一下,基本上这些多做一些产品开
就熟练了

  • 26
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值