SpringBoot 7整合Thymeleaf模板

1.介绍

  Thymeleaf是一个流行的模板引擎,该模板引擎采用Java语言开发
  模板引擎是一个技术名词,是跨领域跨平台的概念,在 Java 语言 体系下有模板引擎,在 C#、PHP 语言体系下也有模板引擎,甚至在 JavaScript 中也会用到模板引擎技术,Java 生态下的模板引擎有 Thymeleaf 、Freemaker、Velocity、Beetl(国产) 等。

  Thymeleaf对网络环境不存在严格的要求,既能用于 Web 环境下, 也能用于非 Web 环境下。在非 Web 环境下,他能直接显示模板上的 静态数据;在 Web 环境下,它能像 Jsp 一样从后台接收数据并替换掉 模板上的静态数据。它是基于 HTML 的,以 HTML 标签为载体, Thymeleaf 要寄托在 HTML 标签下实现。

   SpringBoot 集成了 Thymeleaf 模板技术,并且 Spring Boot 官方也 推荐使用 Thymeleaf 来替代 JSP 技术,Thymeleaf 是另外的一种模板技术,它本身并不属于 Spring Boot,Spring Boot 只是很好地集成这种模 板技术,作为前端页面的数据展示,在过去的 Java Web 开发中,我 们往往会选择使用 Jsp 去完成页面的动态渲染,但是 jsp 需要翻译编 译运行,效率低

  Thymeleaf 的官方网站:http://www.thymeleaf.org

  Thymeleaf 官 方 手 册 : https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html

2.简单实现(获取字符串)

1.创建工程勾选web

2.导入坐标

        <!--SpringBoot 集成Thymeleaf的起步依赖-->
<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

3.在默认配置文件关闭页面缓存

#thymeleaf 页面的缓存开关,默认 true 开启缓存
#建议在开发阶段关闭 thymeleaf 页面缓存,目的实时看到页面
#将工程的启动方式:update resources
spring.thymeleaf.cache=false

#配置模板引擎的前后缀  默认
#spring.thymeleaf.prefix=classpath:templates/
#spring.thymeleaf.suffix=.html

4.templates ->index.html

  • 页面获取后台传递的username 变量
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!--
    普通的html和thymeleaf模板的区别:
        在html标签中添加xmlns:th="www.thymeleaf.org"
    所有thymeleaf的属性都是th:开头的,后面跟着的就是html的属性

    thymeleaf标准变量表达式:获取后台传递过来的属性、对象、集合
        ${key}
-->
<input th:value="${username}" >

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

</body>
</html>

5.controller

@Controller
public class UserController { 
@RequestMapping("/index01")
    public String index01(Model model) {
        model.addAttribute("username", "zhangsan");
        return "index";
    }
}

3.获取User对象

1.Controller

  @RequestMapping("/index02")
    public String index02(Model model) {
        User user = new User();
        user.setName("张三");
        user.setId("123");
        user.setEmail("zhangsan@zhen.com");
        model.addAttribute("user", user);
        return "index-02-user";
    }

2.html

 从model中获取user对象
        使用th:text不止可以获取model中的数据,也可以将标签中的文本进行替换
 --------------------------标准变量表达式--------------------------------
    <table border="1">
        <tr>
            <td>id</td>
            <td>姓名</td>
            <td>邮箱</td>
        </tr>
        <tr>
            <th th:text="${user.id}">110</th>
            <th th:text="${user.name}">张三</th>
            <th th:text="${user.email}">zs@163.com</th>
        </tr>
    </table>

4.选择变量表达式

<!--
    选择变量表达式的语法:
        th:object="${user}" 引用对象
        th:text="*{id}" 将$去掉,将表达式中的user去掉,  *号就代表user对象
出了标签之外就无效 
-->
    <table border="1">
        <tr>
            <td>id</td>
            <td>姓名</td>
            <td>邮箱</td>
        </tr>
        <tr th:object="${user}">
            <th th:text="*{id}">110</th>
            <th th:text="*{name}">张三</th>
            <th th:text="*{email}">zs@163.com</th>
        </tr>
    </table>

5.url表达式@{}

1.Controller

 @RequestMapping("/index03")
    public String index03(Model model) {
        model.addAttribute("username", "zhangsan123");
        return "index-03-path";
    }

2.页面 超链接

<!--
    thymeleaf中的路径:Url表达式
        a       标签的href属性
        form    标签的action属性
        link    标签的href属性
        script  标签的src属性
        img     标签的src属性
        ...
-->

---------------------------a标签----------------------------<br>
<!--
    绝对路径:http://.../templates/user/findById?id=1

    相对路径:http://.../templates/user/user/findById?id=1

    url表达式:使用thymeleaf提供的url表达式,就不会存在相对路径和绝对路径(***)的问题
        th:href="@{/}"
        th:src
        th:action
-->
<a href="/user/findById?id=1">普通的a标签,绝对路径</a>
<br>
<a href="user/findById?id=1">普通的a标签,相对路径</a>
<br>
<a th:href="@{http://localhost:8080/user/findAll}">thymeleaf的a标签,绝对路径</a>
<br>

*****
<a th:href="@{/user/findAll}">thymeleaf的a标签,绝对路径</a>
*****

<br>
<a th:href="@{/user/findAll?id=123}">thymeleaf的a标签,绝对路径,带参数</a>
<br>
<a th:href="@{/user/findAll?id=123&param=${param}}">thymeleaf的a标签,绝对路径,带参数,从表达式中获取</a>
<br>
<!--
    url表达式中的()会被翻译成?
    url表达式中的,会被翻译成&
        http://localhost:8080/user/findAll?id=123&param=zhangsan123
-->
*******
<a th:href="@{/user/findAll(id=123,param=${username})}">thymeleaf的a标签,绝对路径,带参数,从表达式中获取</a>
*******

3.表单 th:action

<!--th:action使用-->
<!--<form method="get" action="/user/findById">-->
<form th:method="get" th:action="@{/user/findById}">
<!--    <input name="id" th:value="123" />-->
    <input type="hidden" name="id" value="123" />
    <input name="username" >
    <button type="submit" >提交</button>
</form>

4.导入脚本th:src

  • js放在resources/static
<!--    使用thymeleaf引用静态资源文件-->
    <script th:src="@{/js/jquery-1.7.2.min.js}"></script>
    
    加载图片
 
<!--加载本地的静态资源图片-->
<img th:src="@{/img/a.jpg}">   
    
<!--加载网络的图片-->
<img th:src="@{https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1599127111527&di=25a9366416ee5f3f73cceebb0de21126&imgtype=0&src=http%3A%2F%2Fimg3.imgtn.bdimg.com%2Fit%2Fu%3D2700654223%2C2122220372%26fm%3D214%26gp%3D0.jpg}">

6.遍历资源th:each

1.Controller

1.list、map、数据,结合的体

存储List 
@RequestMapping("/index04")
    public String index04(Model model) {

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

        for (int i = 0; i < 10; i++) {
            User user = new User();
            user.setId(100 + i + "");
            user.setName("张" + i);
            user.setLoginpwd("1361234567" + i);
            user.setDeptno("北京市大兴区" + i);
            userList.add(user);
        }
        
        model.addAttribute("userList", userList);
        
存储map        

        Map<Integer, Object> userMaps = new HashMap<Integer, Object>();

        for (int i = 0; i < 10; i++) {
            User user = new User();
            user.setId(100 + i + "");
            user.setName("李四" + i);
            user.setLoginpwd("1361234567" + i);
            user.setDeptno("深圳市宝安区" + i);

            userMaps.put(i, user);
        }
        

        model.addAttribute("userMaps", userMaps);
        
// 数组
        User[] userArray = new User[10];

        for (int i = 0; i < 10; i++) {
            User user = new User();
            user.setId(100 + i + "");
            user.setName("赵六" + i);
            user.setLoginpwd("1361234567" + i);
            user.setDeptno("深圳市" + i);
            userArray[i] = user;
        }

        model.addAttribute("userArray", userArray);

    

    
        //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.setName("张三" + k);
                    user.setLoginpwd("1350000000" + k);
                    user.setDeptno("广州市" + i);

                    myUserList.add(user);

                }
                myMap.put(j, myUserList);
            }
            myList.add(myMap);

        }
        model.addAttribute("myList", myList);
        return "index-04-each";
}

2.遍历List

1.方式一:html页面

<!--遍历list集合-->
<table border="1">
<!--    表头-->
    <tr>
        <td>id</td>
        <td>姓名</td>
        <td>密码</td>
        <td>地址</td>
        <td>序号</td>
        <td>索引</td>
<!--        <td>对象</td>-->
    </tr>
<!--    <tr>-->
<!--        <td th:text="${userList[0].id}"></td>-->
<!--    </tr>-->
<!--    语法:变量状态可省略,自动生成的
            th:each="变量名称,变量状态:${集合的名称}"
            th:each="变量名称:${集合的名称}"
            变量的状态:

-->
<!--    <div th:each="user,userStat:${userList}">  效果和下面一样的  -->  
    <div th:each="user:${userList}">
        <tr>
            <td th:text="${user.id}">123</td>
            <td th:text="${user.name}">张三</td>
            <td th:text="${user.loginpwd}">123456</td>
            <td th:text="${user.deptno}">深圳市</td>
<!--            变量状态:
                    count:从1开始计数
                    index:从0开始计数
                    current:当前遍历的对象
                    size:集合的长度
                    first:是否是第一个,true,false
                    last:是否是最后一个,true,false
            -->
            <td th:text="${userStat.count}">深圳市</td>
            <td th:text="${userStat.index}">深圳市</td>
<!--            <td th:text="${userStat.current}">深圳市</td>-->
<!--            <td th:text="${userStat.size}">深圳市</td>-->
<!--            <td th:text="${userStat.first}">深圳市</td>-->
<!--            <td th:text="${userStat.last}">深圳市</td>-->
        </tr>
    </div>
</table>

2.方式二:

  • 效果是一样的
  • 只差在each 之后又是两个 user,userStat

3.遍历Map

<!--
        遍历Map集合
-->
<table border="1">
    <tr>
        <td>key</td>
<!--        <td>value</td>-->
        <td>id</td>
        <td>名称</td>
        <td>密码</td>
        <td>地址</td>
    </tr>
<!--
        语法:
            th:each="键值对变量,集合的状态:${集合变量名称}"
            th:each="键值对变量:${集合变量名称}"
            键值对变量:
                key
                value
-->
    <div th:each="uMap:${userMaps}">
        <tr>
            <td th:text="${uMap.key}"></td>
<!--            <td th:text="${uMap.value}"></td>-->
            <td th:text="${uMap.value.id}"></td>
            <td th:text="${uMap.value.name}"></td>
            <td th:text="${uMap.value.loginpwd}"></td>
            <td th:text="${uMap.value.deptno}"></td>

<!--            <td th:text="${uMapStat.current.key}"></td>-->
<!--            <td th:text="${uMapStat.current.value}"></td>-->
            <td th:text="${uMapStat.count}"></td>
            <td th:text="${uMapStat.index}"></td>

        </tr>
    </div>
</table>

<br>

4.遍历数组

<br>
<!--遍历数组-->
<table border="1">
    <tr>
        <td>索引</td>
        <td>序号</td>
<!--        <td>对象</td>-->
        <td>id</td>
        <td>名称</td>
        <td>密码</td>
        <td>地址</td>
    </tr>

    <div th:each="u:${userArray}">
        <tr>
            <td th:text="${uStat.index}"></td>
            <td th:text="${uStat.count}"></td>
<!--            <td th:text="${uStat.current}"></td>-->
            <td th:text="${u.id}"></td>
            <td th:text="${u.name}"></td>
            <td th:text="${u.loginpwd}"></td>
            <td th:text="${u.deptno}"></td>
        </tr>
    </div>
</table>

<br>

5.复杂的循环

页面

<br>
<!--
    list -> Map -> List -> User
        难点:在遍历map集合的时候,你获取到的是一个Entry对象,里面包含的是键值对
                而不是一个value
-->

    <table border="1">
        <div th:each="listMap:${myList}">
<!--
            Map -> List -> User
-->
            <div th:each="listEntry:${listMap}">
<!--
                List -> User
-->
                <div th:each="uList:${listEntry.value}">
<!--
                    User
-->
                    <div th:each="ur:${uList}">
                        <tr>
                            <td th:text="${ur.id}"></td>
                            <td th:text="${ur.name}"></td>
                            <td th:text="${ur.loginpwd}"></td>
                            <td th:text="${ur.deptno}"></td>
                        </tr>
                    </div>
                </div>
            </div>
        </div>
    </table>

7.条件判断

1.if-else

1.Controller

 @RequestMapping("/index05")
    public String index05(Model model) {
        User user = new User();
        user.setId("123");
        user.setName("张三");
        user.setLoginpwd("1350000000");
        user.setDeptno("广州市");

        model.addAttribute("flag",true);
        model.addAttribute("unFlag",false);
        model.addAttribute("user",user);
        return "index-05-if-unless";
    }

2.html

 <!--
    th:if="${条件}"
        条件为真时,才显示包裹的标签
    th:unless="${条件}"
        条件不为真时,才显示包裹的标签
-->
<!--
    判断布尔值变量
-->
<div th:if="${flag}">
    <span th:text="条件为真时显示的内容"></span>
</div>

<br>

<div th:unless="${unFlag}">
    <span th:text="条件不为真时,显示的内容"></span>
</div>

<!--
    判断对象
        表达式:
            变量值 == null 变量值 eq null
            变量值 != null 变量值 ne null
-->
<br>
<div th:if="${user == null}">
    <span>user为空</span>
</div>
<br>
<div th:if="${user != null}">
    <span th:text="${user}">user</span>
</div>

<br>
<div th:if="${user eq null}">
    <span>user为空</span>
</div>
<br>
<div th:if="${user ne null}">
    <span th:text="${user}">user</span>
</div>
<br>
<div th:unless="${user == null}">
    <span>user为空</span>
</div>
<br>
<div th:unless="${user != null}">
    <span th:text="${user}">user</span>
</div>
<br>

2.switch--case

1.Controller

   @RequestMapping("/index06")
    public String index06(Model model) {

        model.addAttribute("user1","zhangsan");
        model.addAttribute("user2","lisi");
        model.addAttribute("user3","wangwu");
        return "index-06-switch-case";
    }

2.html

选择性匹配
<body>
    <div th:switch="${user1}">
        <span th:case="zhangsan">用户:张三</span>
        <span th:case="lisi">用户:李四</span>
        <span th:case="wangwu">用户:王五</span>
        <span th:case="*">用户:其他</span> default  默认
    </div>

    <br>

    <div th:switch="${user2}">
        <span th:case="zhangsan">用户:张三</span>
        <span th:case="lisi">用户:李四</span>
        <span th:case="wangwu">用户:王五</span>
        <span th:case="*">用户:其他</span>
    </div>

    <br>

    <div th:switch="${user3}">
        <span th:case="zhangsan">用户:张三</span>
        <span th:case="lisi">用户:李四</span>
        <span th:case="wangwu">用户:王五</span>
        <span th:case="*">用户:其他</span>
    </div>

    <br>

    <div th:switch="${user1}">
        <span th:case="lisi">用户:李四</span>
        <span th:case="wangwu">用户:王五</span>
        <span th:case="*">用户:其他</span>
    </div>
</body>

8.th:incline 内联表达式 在html中显示文本

1.controller

   @RequestMapping("/index07")
    public String index07(Model model, HttpServletRequest request) {

        request.getScheme();//http
        request.getServerName();//localhost
        request.getServerPort();//8080
        request.getContextPath();// /index07

        model.addAttribute("user1","caixukun");
        model.addAttribute("user2","tianqi");
        model.addAttribute("user3","huba");

        return "index-07-inline";
    }

2.HTML

<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    
    <script th:inline="javascript">
        // alert("我是:"+[[${user1}]]+",我的爱好是:唱跳、篮球");
        //使用themeleaf的内置对象:必须要添加
        //          #对象名称
        //  #内置对象
        //#httpServletRequest #request
        //#httpSession #session
        //#dates
        //...   
        //scheme 获取协议

        // 
        
        var path = [[${ 
                            #request.scheme + '://' +   
                            #request.serverName + ':' +
                            #request.serverPort + '/' +
                            #request.contextPath+'?'
                   }]];
        alert(path)
    </script>

    
</head>
<body>
<!--
    th:inline
    内敛文本/内敛脚本:
        th:inline="text"/ th:inline="javascript"
-->
   页面上显示的东西
<div th:inline="text">
    [[${user1}]]
    [[${user2}]]
    [[${user3}]]
</div>


</body>

3.内联脚本

 <script th:inline="javascript">
  alert("我是:"+[[${user1}]]+",我的爱好是:唱跳、篮球");
    </script>

4.获取内置对象

 <script th:inline="javascript">
 var path=[[${#httpServletRequest.scheme}]]
  alert(path);
    </script>

5.内置对象

内置功能对象前都需要加#号,内置对象一般都以 s 结尾
官方手册:
http://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html

#dates: java.util.Date 对象的实用方法:
<span th:text="${#dates.format(curDate, 'yyyy-MM-dd
HH:mm:ss')}"></span>
#calendars: 和 dates 类似, 但是 java.util.Calendar 对象;
#numbers: 格式化数字对象的实用方法;
#strings: 字 符 串 对 象 的 实 用 方 法 : contains, startsWith,
prepending/appending 等;
#objects: 对 objects 操作的实用方法;
#bools: 对布尔值求值的实用方法;
#arrays: 数组的实用方法;
#lists: list 的实用方法,比如<span th:text="${#lists.size(datas)}"></span>

#sets: set 的实用方法;
#maps: map 的实用方法;
#aggregates: 对数组或集合创建聚合的实用方法;

9.字面量

字面量:对应数据类型的合法取值,可以在 html 页面直接使用,不需要后台传递

  • 文本自面量
<a th:href="@{'/user/info?id=' + ${user.id}}">查看用户:文本字面的路径使用</a><br/>
  • 数字
<span th:text="2019 + 20">1969</span>年<br/>
  • boolean 字面量
<div th:if="${true}">执行成功</div>
  • null 字面量
<span th:if="${user ne null}">用户不为空</span><br/>

1.Thymeleaf 字符串拼接

1.Controller

 @RequestMapping("/index08")
    public String index08(Model model, HttpServletRequest request) {

//        request.getScheme();//http
//        request.getServerName();//localhost
//        request.getServerPort();//8080
//        request.getContextPath();// /index07

        model.addAttribute("username","蔡徐坤");
        model.addAttribute("hobby1","唱");
        model.addAttribute("hobby2","跳");
        model.addAttribute("hobby3","篮球");

        return "index-08-zimianliang";
    }

2.html

<!--
        通过优雅的方式拼接字符串和字面量
            th:text="|我是:${username},爱好:${hobby1}、${hobby2}、${hobby3}|"
-->
<!--Could not parse as expression,如果在字符串与字面量拼接的时候,不使用双竖线,则无法解析该表达式-->
<!--        <span th:text="我是:${username},爱好:${hobby1}、${hobby2}、${hobby3}"></span>-->
<!--这种方式最常用-->
<span th:text="|我是:${username},爱好:${hobby1}、${hobby2}、${hobby3}|"></span>

gt lt ge le

eq ne

2.三元运算符

<!--三元运算符-->
<span th:text="${username eq '蔡徐坤' ? '1':'2'}"></span>
posted @ 2020-10-02 18:07  Tony小哥  阅读(450)  评论(1编辑  收藏  举报