第六天(springBoot基础第三篇)

发布时间 2023-03-22 21:10:48作者: 解灵

一、 Thymeleaf模板

1. 介绍

Thymeleaf是用来开发Web和独立环境项目的现代服务器端Java模板引擎。
Thymeleaf的主要目标是为您的开发工作流程带来优雅的自然模板 - HTML。可以在直接浏览器中正确显示,
并且可以作为静态原型,从而在开发团队中实现更强大的协作。
借助Spring Framework的模块,可以根据自己的喜好进行自由选择,可插拔功能组件,Thymeleaf是现代
HTML5 JVM Web开发的理想选择 - 尽管它可以做的更多。
Spring官方支持的服务的渲染模板中,并不包含jsp。而是Thymeleaf和Freemarker等,而Thymeleaf与
SpringMVC的视图技术,及SpringBoot的自动化配置集成非常完美,几乎没有任何成本,你只用关注
Thymeleaf的语法即可。
特点:
1.动静结合:Thymeleaf 在有网络和无网络的环境下皆可运行,即它可以让美工在浏览器查看页面的静态
效果,也可以让程序员在服务器查看带数据的动态页面效果。这是由于它支持 html 原型,然后在 html
标签里增加额外的属性来达到模板+数据的展示方式。浏览器解释 html 时会忽略未定义的标签属性,
所以 thymeleaf 的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静
态内容,使页面动态显示。
2.开箱即用:它提供标准和spring标准两种方言,可以直接套用模板实现JSTL、 OGNL表达式效果,避免
每天套模板、该jstl、改标签的困扰。同时开发人员也可以扩展和创建自定义的方言。
多方言支持:Thymeleaf 提供spring标准方言和一个与 SpringMVC 完美集成的可选模块,可以快速的
实现表单绑定、属性编辑器、国际化等功能。
 
3·与SpringBoot完美整合,SpringBoot提供了Thymeleaf的默认配置,并且为Thymeleaf设置了视图解
析器,我们可以像以前操作jsp一样来操作Thymeleaf。代码几乎没有任何区别,就是在模板语法上有区
别。

2 基本设置

1 创建环境
勾选web和Thymeleaf的依赖:
2 默认配置
不需要做任何配置,启动器已经帮我们把Thymeleaf的视图器配置完成
3 快速开始

我们准备一个controller,控制视图跳转:

@Controller
public class HelloController {
@GetMapping("show1")
public String show1(Model model){
model.addAttribute("msg", "Hello, Thymeleaf!");
return "hello";
}
}
新建一个html模板
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>hello</title>
</head>
<body>
<h1 th:text="${msg}">大家好</h1>
</body>
</html>
注意,把html 的名称空间,改成: xmlns:th="http://www.thymeleaf.org" 会有语法提示
 

三 语法

Thymeleaf的主要作用是把model中的数据渲染到html中,因此其语法主要是如何解析model中的数据。从
以下方面来学习:
变量、方法、条件判断、循环、运算、逻辑运算、、布尔运算、比较运算、条件运算、其它
1 变量
我们先新建一个实体类:User
public class User {
String name;
int age;
User friend;// 对象类型属性
}
然后在模型中添加数据
@GetMapping("show2")
public String show2(Model model){
User user = new User();
user.setAge(21);
user.setName("Jack Chen");
user.setFriend(new User("李小龙", 30));
model.addAttribute("user", user);
return "show2";
}
语法说明:
Thymeleaf通过 ${} 来获取model中的变量,注意这不是el表达式,而是ognl表达式,但是语法非常像。
示例:
我们在页面获取user数据:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>用户页面</title>
</head>
<body>
<div th:text="${user.name}"></div>
</body>
</html>
语法说明:
Thymeleaf通过 ${} 来获取model中的变量,注意这不是el表达式,而是ognl表达式,但是语法非常像。
示例:
我们在页面获取user数据:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>用户页面</title>
</head>
<body>
<div th:text="${user.name}"></div>
</body>
</html>
效果:
感觉跟el表达式几乎是一样的。不过区别在于,我们的表达式写在一个名为: th:text 的标签属性中,这个
叫做 指令
动静结合
指令:
Thymeleaf崇尚 自然模板 ,意思就是模板是纯正的html代码,脱离模板引擎,在纯静态环境也可以直接运
行。现在如果我们直接在html中编写 ${} 这样的表达式,显然在静态环境下就会出错,这不符合Thymeleaf
的理念。
Thymeleaf中所有的表达式都需要写在 指令 中,指令是HTML5中的自定义属性,在Thymeleaf中所有指令都
是以 th: 开头。因为表达式 ${user.name} 是写在自定义属性中,因此在静态环境下,表达式的内容会被当
做是普通字符串,浏览器会自动忽略这些指令,这样就不会报错了!
静态页面中, th 指令不被识别,但是浏览器也不会报错,把它当做一个普通属性处理。这样 span 的默
认值 请登录 就会展现在页面
如果是在Thymeleaf环境下, th 指令就会被识别和解析,而 th:text 的含义就是替换所在标签中的文
本内容,于是 user.name 的值就替代了 span 中默认的请登录
指令的设计,正是Thymeleaf的高明之处,也是它优于其它模板引擎的原因。动静结合的设计,使得无论是
前端开发人员还是后端开发人员可以完美契合。
 
但是要注意,如果浏览器不支持Html5怎么办?
如果不支持这种 th: 的命名空间写法,那么可以把 th:text 换成 data-th-text ,Thymeleaf也可以兼容。
escape
另外, th:text 指令出于安全考虑,会把表达式读取到的值进行处理,防止html的注入。
例如, <p>你好</p> 将会被格式化输出为 $lt;p$gt;你好$lt;/p$lt; 。
如果想要不进行格式化输出,而是要输出原始内容,则使用 th:utext 来代替.
ognl表达式的语法糖
刚才获取变量值,我们使用的是经典的 对象.属性名 方式。但有些情况下,我们的属性名可能本身也是变量,
怎么办?
ognl提供了类似js的语法方式:
例如: ${user.name} 可以写作 ${user['name']}
 

2方法

<h2 th:object="${user}">
<p>FirstName: <span th:text="*{name.split(' ')[0]}">Jack</span>.</p>
<p>LastName: <span th:text="*{name.split(' ')[1]}">Li</span>.</p>
</h2>

 

 

Thymeleaf提供的全局对象:

 

 

举例
我们在环境变量中添加日期类型对象
1 @GetMapping("show3")
2 public String show3(Model model){
3 model.addAttribute("today", new Date());
4 return "show3";
5 }
在页面中处理 1 <p> 2 今天是: <span th:text="${#dates.format(today,'yyyy-MM-dd')}">2018-04-25</span> 3 </p> 

4 字面值

有的时候,我们需要在指令中填写基本类型如:字符串、数值、布尔等,并不希望被Thymeleaf解析为变
量,这个时候称为字面值。
字符串字面值
使用一对 ' 引用的内容就是字符串字面值了: 1 <p>你正在观看 <span th:text="'thymeleaf'">template</span> 的字符串常量值.</p> 
th:text 中的thymeleaf并不会被认为是变量,而是一个字符串
数字字面值
数字不需要任何特殊语法, 写的什么就是什么,而且可以直接进行算术运算
 1 <p>今年是 <span th:text="2018">1900</span>.</p>
2<p>两年后将会是 <span th:text="2018 + 2">1902</span>.</p> 
布尔字面值
布尔类型的字面值是true或false:
<div th:if="true">
你填的是true
</div>
这里引用了一个 th:if 指令,跟vue中的 v-if 类似

5 拼接

我们经常会用到普通字符串与表达式拼接的情况:
<span th:text="'欢迎您:' + ${user.name} + '!'"></span>
字符串字面值需要用 '' ,拼接起来非常麻烦,Thymeleaf对此进行了简化,使用一对 | 即可:
<span th:text="|欢迎您:${user.name}|"></span>
与上面是完全等效的,这样就省去了字符串字面值的书写。

6 运算

(1)算术运算
支持的算术运算符: + - * / %
<span th:text="${user.age}"></span>
<span th:text="${user.age}%2 == 0"></span>
比较运算
支持的比较运算: > , < , >= and <= ,但是 > , < 不能直接使用,因为xml会解析为标签,要使用别名。
注意 == and != 不仅可以比较数值,类似于equals的功能。
可以使用的别名: gt (>), lt (<), ge (>=), le (<=), not (!). Also eq (==), neq/ne (!=).
(2)条件运算
          三元运算
<span th:text="${user.sex} ? '男':'女'"></span>
三元运算符的三个部分:conditon ? then : else
condition:条件
then:条件成立的结果
else:不成立的结果
其中的每一个部分都可以是Thymeleaf中的任意表达式。
默认值
有的时候,我们取一个值可能为空,这个时候需要做非空判断,可以使用 表达式 ?: 默认值 简
写:(了解即可)
<span th:text="${user.name} ?: '二狗'"></span>
当前面的表达式值为null时,就会使用后面的默认值。
注意: ?: 之间没有空格。

7 循环

循环也是非常频繁使用的需求,我们使用 th:each 指令来完成:
假如有用户的集合:users在Context中。
<tr th:each="user : ${users}">
<td th:text="${user.name}">Onions</td>
<td th:text="${user.age}">2.41</td>
</tr>
${users} 是要遍历的集合,可以是以下类型:
Iterable,实现了Iterable接口的类
Enumeration,枚举
Interator,迭代器
Map,遍历得到的是Map.Entry
Array,数组及其它一切符合数组结果的对象
 
在迭代的同时,我们也可以获取迭代的状态对象:
<tr th:each="user,stat : ${users}">
<td th:text="${user.name}">Onions</td>
<td th:text="${user.age}">2.41</td>
</tr>
stat对象包含以下属性:
index,从0开始的角标
count,元素的个数,从1开始
size,总元素个数
current,当前遍历到的元素
even/odd,返回是否为奇偶,boolean值
first/last,返回是否为第一或最后,boolean值

8 逻辑判断

有了 if和else ,我们能实现一切功能^_^。
Thymeleaf中使用 th:if 或者 th:unless ,两者的意思恰好相反
<span th:if="${user.age} < 24">小鲜肉</span>
如果表达式的值为true,则标签会渲染到页面,否则不进行渲染。
以下情况被认定为true:
表达式值为true
表达式值为非0数值
表达式值为非0字符
表达式值为字符串,但不是 "false" , "no" , "off"
表达式不是布尔、字符串、数字、字符中的任何一种
其它情况包括null都被认定为false

9 样式及脚本引入

https://blog.csdn.net/qq_37256896/article/details/107007485

10.分页

(1)分页工具类:

/**
 * <p>
 *  自制分页工具类
 * </p>
 *
 * @author sunwz
 * @version 1.0
 * @since 2023/3/20 15:52
 */
@Data
public class PageInfo<T> {

    /* 当前页 */
    private int pageNum;

    /* 上一页 */
    private int prePage;

    /* 下一页 */
    private int nextPage;

    /* 总页数 */
    private int pages;

    /* 总条数 */
    private int total;

    /* 每页多少条 */
    private int pageSize;

    /* 查询的起始索引 */
    private int startIndex;

    private List<T> list;


    public PageInfo (int pageNum, int total, int pageSize) {

        this.pageNum = pageNum;
        this.total = total;
        this.pageSize = pageSize;

        this.prePage = this.pageNum  > 1 ? this.pageNum - 1 : 1;

        /* 总条数 / 每页多少条   */
        this.pages = (this.total / this.pageSize) + (this.total % this.pageSize != 0?1:0);

        /* 下一页 */
        this.nextPage = this.pageNum >= this.pages ? this.pages : this.pageNum + 1;

        /* 起始索引 (当前页 -1 ) * pageSize  */
        this.startIndex = (this.pageNum - 1) * pageSize;
    }
}

(2)前端的代码

总条数:<span th:text="${pageInfo.total}"></span>,
<span th:text="${pageInfo.pageNum}"></span>/<span th:text="${pageInfo.pages}"></span>
<a href="/shares/queryList?pageNum=1">首页</a>
<a th:href="|/shares/queryList?pageNum=${pageInfo.prePage}&pageSize=${pageInfo.pageSize}|">上一页</a>
<a th:href="|/shares/queryList?pageNum=${pageInfo.nextPage}&pageSize=${pageInfo.pageSize}|">下一页</a>
<a th:href="|/shares/queryList?pageNum=${pageInfo.pages}&pageSize=${pageInfo.pageSize}|">尾页</a>