SpringBoot集成Thymeleaf从入门到精通(全)

简介: 目录SpringBoot集成Thymeleaf1. 关闭缓存2. 表达式3. 常用属性4. 遍历元素5. 条件判断6. 字面量7. 字符串拼接8. 数学运算SpringBoot集成ThymeleafThymeleaf 是一个流行的模板引擎,该模板引擎采用 Java 语言开发Thymeleaf 是另外的一种模板技术,它本身并不属于 Spring Boot,Spring Boot只是很好地集成这种模板技术,作为前端页面的数据展示在创建模板的时候还需要多选择一个这个之后默认会自动添加这些依赖Sp

本篇文章的学习
在这之前可以补充springboot的基础
详情可看我之前的文章

springboot从入门到精通(全)

SpringBoot集成Thymeleaf

  • Thymeleaf 是一个流行的模板引擎,该模板引擎采用 Java 语言开发
  • Thymeleaf 是另外的一种模板技术,它本身并不属于 Spring Boot,Spring Boot只是很好地集成这种模板技术,作为前端页面的数据展示

在创建模板的时候还需要多选择一个这个在这里插入图片描述
之后默认会自动添加这些依赖
在这里插入图片描述

==Springboot 使 用 thymeleaf 作 为 视 图 展 示 , 约 定 将 模 板 文 件 放 置在src/main/resource/templates 目录下,静态资源放置在 src/main/resource/static 目录下==
创建一个控制层面

@Controller
public class UserController {

    @RequestMapping(value = "/message")
    public String message(Model model) {

        model.addAttribute("data","SpringBoot集成Thymeleaf模版引擎");

        return "message";
    }
}

页面这个要配置在特定的目录下
还要加上名称空间才能用她的函数xmlns:th="http://www.thymeleaf.org"
具体使用名称空间的text后的数据,如果有数据传入就会将其替代,如果没有数据才会显示后面的内容
具体底层是html,通过这个名称空间,以及他的函数才可以进行加载识别参数

xmlns:th="http://www.thymeleaf.org"
xmlns -> 命名空间
命名空间后面的地址是一个约束文件,约束你使用thymeleaf表达式
的一个规则文件,就好比我们之前在xml文件中的一此dtd文件

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--
    thymeleaf模版引擎的页面必须得通过中央调度器
-->
<h2 th:text="${data}">展示要显示的内容0</h2>
</body>
</html>

配置后启动

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

也可以配置一个视图解析器
默认是有视图解析器的
所谓的视图解析器,下面才是真实跳转的路径

#设置thymeleaf模版引擎的前/后缀,(可选项)
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html

为什么使用了th前缀就可以获取后台数据?
那是因为项目中添加了thymeleaf的核心依赖,它的核心依赖会去
解析thymeleaf自己定义的这些标签名称,通过thymeleaf自己的java核心代码来获取我们的后台数据

html 不会认识${}语法。
请求的流程是,发送请求给服务器,服务器接收请求后,处理请求,跳转到指定的静态 html 页面,在服务器端,Thymeleaf 模板引擎会按照它的语法,对动态数据进行处理,
所以如果要是 th 开头,模板引擎能够识别,会在服务器端进行处理,获取数据;如果没有以 th 开头,那么 Thymeleaf 模板引擎不会处理,直接返回给客户端了

1. 关闭缓存

不用再进行编译只有修改代码,刷新网页就会有显示

#设置thymeleaf模版引擎的缓存,设置为false关闭,默认为true开启
spring.thymeleaf.cache=false

之所以thymeleaf可以代替jsp,是因为jsp要渲染,编译了才可执行

还需要额外配置启动的更新资源在这里插入图片描述

2. 表达式

要配置一个依赖

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

Thymeleaf 中的变量表达式使用 ${变量名} 的方式获取 Controller 中 model 其中的数据

th:text="" 是 Thymeleaf 的一个属性,用于文本的显示

  • 向 model 放入 User 对象
public class User {

    private Integer id;

    private String username;

    private Integer age;

    public Integer getId() {
        return id;
    }

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

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}
  • 创建 user.html 页面获取 User 对象数据
@RequestMapping(value = "/user/detail")
public ModelAndView userDetail() {
    ModelAndView mv = new ModelAndView();
    User user = new User();
    user.setId(1001);
    user.setAge(23);
    user.setUsername("lisi");

    mv.setViewName("userDetail");
    mv.addObject("user",user);

    return mv;
}

==标准变量表达式== ${} (推荐)
html页面的主要功能

<h1>标准变量表达式:${} -> (推荐)</h1>
用户编号:<span th:text="${user.id}"></span><br/>
用户姓名:<span th:text="${user.username}"></span><br/>
用户年龄:<span th:text="${user.age}"></span><br/>

==选择变量表达式==

*{}必须使用th:object属性来绑定这个对象
在div子标签中使用*来代替绑定的对象${user}

<h1>选择变量表达式(星号表达式):*{} -> (不推荐)</h1>
<!--
    *{}必须使用th:object属性来绑定这个对象
    在div子标签中使用*来代替绑定的对象${user}
-->
<div th:object="${user}">
    用户编号:<span th:text="*{id}"></span><br/>
    用户姓名:<span th:text="*{username}"></span><br/>
    用户年龄:<span th:text="*{age}"></span><br/>
</div>

<h1>标准变量表达式与选择变量表达式的混合使用(不推荐)</h1>
用户编号<span th:text="*{user.id}"></span><br/>
用户年龄<span th:text="*{user.age}"></span><br/>
用户姓名<span th:text="*{user.username}"></span><br/>

下面讲解的是路径表达式中常用的区别
==路径表达式== @{...}

  • 绝对路径跳转(不带参数)
<a href="http://www.baidu.com">传统写法:跳转至百度</a><br/>
<a th:href="@{http://www.bjpowernode.com}">路径表达式:路径到动力节点</a><br/>
<a th:href="@{http://localhost:8080/user/detail1}">跳转至:/user/detail1</a><br/>
<a href="http://localhost:8080/user/detail1">传统写法跳转至:/user/detail1</a><br/>
  • 相对路径跳转(不带参数)
<h2>URL路径表达式,相对路径[没有参数](实际开发中推荐使用的)</h2>
<a th:href="@{/user/detail1}">跳转至:/user/detail1</a><br/>
  • 绝对路径跳转(带参数)
<h2>绝对路径(带参数)(不推荐使用)</h2>
<a href="http://localhost:8080/test?username='zhangsan'">绝对路径,带参数:/test,并带参数username</a><br/>
<a th:href="@{http://localhost:8080/test?username=zhangsan}">路径表达工写法,带参数:/test,并带参数username</a><br/>
  • 相对路径跳转(带参数)
<h2>相对路径(带参数)</h2>
<a th:href="@{/test?username=lisi}">相对路径,带参数</a>

<h2>相对路径(带参数:后台获取的参数值)</h2>
<!--/test?username=1001-->
<a th:href="@{'/test?username='+${id}}">相对路径:获取后台参数值</a>

<h2>相对路径(带多个参数:后台获取的参数值)</h2>
<!--
    /test1?id=1001&username=zhaoliu&age=28
-->
<a th:href="@{'/test1?id='+${id}+'&username='+${username}+'&age='+${age}}">相对路径(带多个参数:后台获取的参数值)</a>
<a th:href="@{/test1(id=${id},username=${username},age=${age})}">强烈推荐使用:@{}相对路径(带多个参数:后台获取的参数值)</a><br/>
<a th:href="@{'/test2/'+${id}}">请求路径为RESTful风格</a><br/>
<a th:href="@{'/test3/'+${id}+'/'+${username}}">请求路径为RESTful风格</a><br/>

在控制层面的代码为

@RequestMapping(value = "/user/detail1")
public String userDetail1(Model model) {
    User user = new User();
    user.setId(1002);
    user.setAge(24);
    user.setUsername("wangwu");

    model.addAttribute("user",user);

    return "userDetail";
}

@RequestMapping(value = "/url")
public String urlExpression(Model model) {

    model.addAttribute("id",1001);
    model.addAttribute("age",28);
    model.addAttribute("username","zhaoliu");

    return "url";
}


@RequestMapping(value = "/test")
public @ResponseBody String test(String username) {
    return "请求路径/test,参数是:" + username;
}

@RequestMapping(value = "/test1")
public @ResponseBody String test1(Integer id,String username,Integer age) {
    return "请求路径/test1,参数id=" + id+",username="+username+",age="+age;
}

@RequestMapping(value = "/test2/{id}")
public @ResponseBody String test2(@PathVariable("id") Integer id) {
    return "ID="+id;
}

@RequestMapping(value = "/test3/{id}/{username}")
public @ResponseBody String test3(@PathVariable("id") Integer id,
                                  @PathVariable("username") String username) {
    return "ID="+id+"----username="+username;
}

3. 常用属性

属性 描述
th:action th:action 定义后台控制器的路径,类似标签的 action 属性,主要结合 URL 表达式,获取动态变量
th:method 设置请求方法
th:href 定义超链接,主要结合 URL 表达式,获取动态变量
th:src 用于外部资源引入,比如<script>标签的 src 属性,<img>标签的 src 属性,常与@{}表达式结合使用,在 SpringBoot 项目的静态资源都放到 resources 的 static 目录下。放到 static 路径下的内容,写路径时不需要写上 static
th:id 类似 html 标签中的 id 属性
th:name 设置名称
th:value 类似 html 标签中的 value 属性,能对某元素的 value 属性进行赋值
th:attr 给 HTML 中某元素的某属性赋值,好处是可以给 html 中没有定义的属性动态的赋值
th:text 用于文本的显示,该属性显示的文本在标签体中,如果是文本框,数据会在文本框外显示,要想显示在文本框内,使用 th:value
th:object 用于数据对象绑定,通常用于选择变量表达式(星号表达式)
th:onclick 点击按钮
th:style 设置样式
th:each 后台传来一个对象集合那么就可以使用此属性遍历输出,它与JSTL 中的<c: forEach>类似,此属性既可以循环遍历集合,也可以循环遍历数组及 Map
th:inline 有三个取值类型 (text, javascript 和 none),值为 none 什么都不做,没有效果

比如

<form method="get" action="http://localhost:8080/test1">
    用户编号:<input type="text" name="id" /><br/>
    用户姓名:<input type="text" name="username" /><br/>
    用户年龄<input type="text" name="age" /><br/>
    <input type="submit" value="submit"/>
</form>

内敛文本(th:inline=”text”)

<div th:inline="text">

    数据:[[${data}]]

</div>
//或者直接使用
数据outside:[[${data}]]

内敛脚本(th:inline=”javascript”)

<h1>内敛脚本 th:inline="javascript"</h1>
<script type="text/javascript"  th:inline="javascript">
    function showData() {
        alert([[${data}]]);
        alert("----");
    }
</script>
<button th:onclick="showData()">展示数据</button>

4. 遍历元素

此处只po出关键代码

==遍历List 集合==

@RequestMapping("/each/list")
public String eachList(Model model) {
    List<User> userList = new ArrayList<User>();

    for (int i = 0; i < 10; i++) {
        User user = new User();
        user.setId(100 + i);
        user.setNick("张" + i);
        user.setPhone("1361234567" + i);
        user.setAddress("北京市大兴区" + i);
        userList.add(user);
    }
    model.addAttribute("userList", userList);
    model.addAttribute("data", "SpringBoot");
    return "eachList";
}

user 当前循环的对象变量名称(随意)
userStat 当前循环对象状态的变量(可选默认就是对象变量名称+Stat)
${userList} 当前循环的集合

count: 当前迭代对象的个数(从 1 开始计算)这两个用的较多
size: 被迭代对象的大小
current: 当前迭代变量
even/odd: 布尔值,当前循环是否是偶数/奇数(从 0 开始计算)
first: 布尔值,当前循环是否是第一个
last: 布尔值,当前循环是否是最后一个
注意:循环体信息 interStat 也可以不定义,则默认采用迭代变量加上 Stat 后缀,即 userStat

<div th:each="user,userStat:${userList}">
    <span th:text="${userStat.index}"></span>
    <span th:text="${userStat.count}"></span>
    <span th:text="${user.id}"></span>
    <span th:text="${user.nick}"></span>
    <span th:text="${user.phone}"></span>
    <span th:text="${user.address}"></span>
</div>

<div></div>
<div th:each="user:${userList}">
    <span th:text="${userStat.index}"></span>
    <span th:text="${userStat.count}"></span>
    <span th:text="${user.id}"></span>
    <span th:text="${user.nick}"></span>
    <span th:text="${user.phone}"></span>
    <span th:text="${user.address}"></span>
</div>

==遍历Map 集合==

@RequestMapping(value = "/each/map")
public String eachMap(Model model) {
    Map<Integer, Object> userMaps = new HashMap<Integer, Object>();

    for (int i = 0; i < 10; i++) {
        User user = new User();
        user.setId(i);
        user.setNick("李四" + i);
        user.setPhone("1390000000" + i);
        user.setAddress("天津市" + i);
        userMaps.put(i, user);
    }
    model.addAttribute("userMaps", userMaps);
    return "eachMap";
}
<div th:each="userMap,userMapStat:${userMaps}">
    <span th:text="${userMapStat.count}"></span>
    <span th:text="${userMapStat.index}"></span>
    <span th:text="${userMap.key}"></span>
    <span th:text="${userMap.value}"></span>
    <span th:text="${userMap.value.id}"></span>
    <span th:text="${userMap.value.nick}"></span>
    <span th:text="${userMap.value.phone}"></span>
    <span th:text="${userMap.value.address}"></span>
</div>


<div th:each="userMap:${userMaps}">
    <span th:text="${userMapStat.count}"></span>
    <span th:text="${userMapStat.index}"></span>
    <span th:text="${userMap.key}"></span>
    <span th:text="${userMap.value}"></span>
    <span th:text="${userMap.value.id}"></span>
    <span th:text="${userMap.value.nick}"></span>
    <span th:text="${userMap.value.phone}"></span>
    <span th:text="${userMap.value.address}"></span>
</div>

==遍历数组==

@RequestMapping(value = "/each/array")
public String eachArray(Model model) {

    User[] userArray = new User[10];

    for (int i = 0; i < 10; i++) {

        User user = new User();
        user.setId(i);
        user.setNick("赵六" + i);
        user.setPhone("1380000000" + i);
        user.setAddress("深圳市" + i);
        userArray[i] = user;

    }
    model.addAttribute("userArray", userArray);
    return "eachArray";
}
<h1>循环遍历Array数组(使用方法同list一样)</h1>
<div th:each="user,userStat:${userArray}">
    <span th:text="${userStat.index}"></span>
    <span th:text="${userStat.count}"></span>
    <span th:text="${user.id}"></span>
    <span th:text="${user.nick}"></span>
    <span th:text="${user.phone}"></span>
    <span th:text="${user.address}"></span>
</div>

==遍历混合组合==
List 里面放 Map,Map 里面又放的是 List
在这里插入图片描述

@RequestMapping(value = "/each/all")
public String eachAll(Model model) {
    //list -> Map -> List -> User
    List<Map<Integer, List<User>>> myList = new ArrayList<Map<Integer, List<User>>>();

    for (int i = 0; i < 2; i++) {

        Map<Integer, List<User>> myMap = new HashMap<Integer, List<User>>();
        for (int j = 0; j < 2; j++) {
            List<User> myUserList = new ArrayList<User>();
            for (int k = 0; k < 3; k++) {
                User user = new User();
                user.setId(k);
                user.setNick("张三" + k);
                user.setPhone("1350000000" + k);
                user.setAddress("广州市" + i);
                myUserList.add(user);
            }
            myMap.put(j, myUserList);
        }
        myList.add(myMap);

    }
    model.addAttribute("myList", myList);
    return "eachAll";
}
<h2>循环遍历复杂集合:list -> Map -> list -> User</h2>
<div th:each="myListMap:${myList}">
    <div th:each="myListMapObj:${myListMap}">
        Map集合的key:<span th:text="${myListMapObj.key}"></span>
        <div th:each="myListMapObjList:${myListMapObj.value}">
            <span th:text="${myListMapObjList.id}"></span>
            <span th:text="${myListMapObjList.nick}"></span>
            <span th:text="${myListMapObjList.phone}"></span>
            <span th:text="${myListMapObjList.address}"></span>
        </div>
    </div>
</div>

5. 条件判断

控制层类的代码没变

@Controller
public class UserController {

    @RequestMapping(value = "/condition")
    public String condition(Model model) {

        model.addAttribute("sex",1);

        model.addAttribute("flag",true);

        model.addAttribute("productType",0);


        return "condition";
    }
}

主要的区别是在于
下面的判断语句
==if判断==

<h1>th:if 用法:如果满足条件显示(执行),否则相反</h1>
<div th:if="${sex eq 1}">
    男
</div>
<div th:if="${sex eq 0}">
    女
</div>

==unless判断==

<h1>th:unless 用法:与th:if用法相反,即条件判断取反</h1>
<div th:unless="${sex ne 1}">
    女
</div>

==switch判断==

<h1>th:switch/th:case用法</h1>
<div th:switch="${productType}">
    <span th:case="0">产品0</span>
    <span th:case="1">产品1</span>
    <span th:case="*">无此产品</span>
</div>

6. 字面量

字面量主要有

  • 文本字面量,用单引号'....'的字符串就是字面量
  • 数字字面量,用双引号数字就是字面量
  • boolean字面量
  • null字面量

主要的部分代码展示如下

<h1>文本字面量,用单引号'....'的字符串就是字面量</h1>
<a th:href="@{'/user/detail?sex=' + ${sex}}">查看性别</a>
<span th:text="Hello"></span>

<h1>数字字面量</h1>
今年是<span th:text="2020">1949</span>年<br/>
20年后是<span th:text="2020+20">1969</span>年<br/>

<h1>boolean字面量</h1>
<div th:if="${flag}">
    执行成功
</div>
<div th:if="${!flag}">
    不成功
</div>

<h1>null字面量</h1>
<span th:text="${user.id}"></span>
<div th:unless="${userDetail eq null}">
    对象已创建,地址不为空
</div>

<div th:if="${userDetail.id eq null}">
    空
</div>

7. 字符串拼接

这个拼接类似java代码
在html代码中的展示

<span th:text="'共'+${totalRows}+'条'+${totalPage}+'页,当前第'+${currentPage}+'页,首页 上一页 下一页 尾页'">共120条12页,当前第1页,首页 上一页 下一页 尾页</span>

8. 数学运算

三元运算 :表达式?” 正确结果”:” 错误结果”
算术运算:+ , - , * , / , %
关系比较:> , < , >= , <= ( gt , lt , ge , le )
相等判断:== , != ( eq , ne )

表达式 描述
ne not equal
eq equal
ge great equal
le little equal
gt great
lt little

部分代码展示

<h1>三元运算符 表达式?正确:错误</h1>
<div th:text="${sex eq 1 ? '男':'女'}"></div>
<div th:text="${sex == 1 ? '男':'女'}"></div>

<h1>算术运算</h1>
20+5=<span th:text="20+5"></span><br/>
20-5=<span th:text="20-5"></span><br/>
20*5=<span th:text="20*5"></span><br/>
20/5=<span th:text="20/5"></span><br/>
20%3=<span th:text="20%3"></span><br/>

<h1>关系比较</h1>
5>2为<span th:if="5 gt 2">真</span><br/>
5>2为<span th:if="5 > 2">真</span><br/>
5<2<span th:unless="5 lt 2">真</span><br/>
5<2<span th:unless="5 < 2">真</span><br/>
1>=1<span th:if="1 ge 1">真</span><br/>
1>=1<span th:if="1 >= 1">真</span><br/>
1<=1<span th:if="1 le 1">真</span><br/>
1<=1<span th:if="1 <= 1">真</span><br/>

<h1>相等判断</h1>
<span th:if="${sex == 1}">男</span>
<span th:if="${sex eq 1}">男</span>
<span th:unless="${sex ne 1}">女</span>
相关文章
|
17天前
|
消息中间件 Java Kafka
Springboot集成高低版本kafka
Springboot集成高低版本kafka
|
24天前
|
NoSQL Java Redis
SpringBoot集成Redis解决表单重复提交接口幂等(亲测可用)
SpringBoot集成Redis解决表单重复提交接口幂等(亲测可用)
261 0
|
29天前
|
NoSQL Java Redis
SpringBoot集成Redis
SpringBoot集成Redis
403 0
|
1月前
|
NoSQL Java Redis
小白版的springboot中集成mqtt服务(超级无敌详细),实现不了掐我头!!!
小白版的springboot中集成mqtt服务(超级无敌详细),实现不了掐我头!!!
269 1
|
2天前
|
Java 关系型数据库 数据库
【SpringBoot系列】微服务集成Flyway
【4月更文挑战第7天】SpringBoot微服务集成Flyway
【SpringBoot系列】微服务集成Flyway
|
17天前
|
SQL Java 调度
SpringBoot集成quartz定时任务trigger_state状态ERROR解决办法
SpringBoot集成quartz定时任务trigger_state状态ERROR解决办法
|
25天前
|
NoSQL Java Redis
SpringBoot集成Redis
SpringBoot集成Redis
53 1
|
28天前
|
Java 测试技术 Maven
SpringBoot集成Elasticsearch
SpringBoot集成Elasticsearch
24 0
|
1月前
|
XML Java 关系型数据库
【SpringBoot系列】SpringBoot集成Fast Mybatis
【SpringBoot系列】SpringBoot集成Fast Mybatis