【SpringBoot整合系列】SpringBoot整合Thymeleaf

目录

  • 背景
  • Thymeleaf
    • 简介
    • Thymeleaf的特征
    • 模板引擎是什么
  • 代码示例
    • 1.引入依赖
    • 2.修改配置文件,添加Thymeleaf的配置信息
    • 3.编写HTML模板文件
    • 4.编写控制器,返回ModelAndView,进行视图渲染
  • Thymeleaf语法
    • 1.常用标签/属性
      • 1.1 th:action
      • 1.2 th:method
      • 1.3 th:href
      • 1.4 th:src
      • 1.5 th:text
      • 1.6 th:style
      • 1.7 th:each
        • 1.7.1 循环 List
          • 语法说明
        • 1.7.2 循环 Map
      • 1.8 条件if
      • 1.9 switch,case 判断语句
      • 1.10 th:inline
        • 1.10.1 内联text
        • 1.10.2 内联javaScript
    • 2.表达式
      • 2.1 标准变量表达式
      • 2.2 选择变量表达式
      • 2.3 链接表达式(URL 表达式)
    • 3.字面量
      • 3.1 文本字面量
      • 3.2 数字字面量
      • 3.3 boolean字面量
      • 3.4 null字面量
    • 4. 字符串连接
    • 5.运算符
      • 5.1 算术运算:
      • 5.2 关系比较:
      • 5.3 布尔运算符:
      • 5.4 条件运算符:
    • 6.Thymeleaf 基本对象
    • 7.Tymeleaf 内置工具类对象
      • 示例(后台)
      • 示例(前端)
    • 8.模板
      • 8.1定义模板
      • 8.2 引用模板
      • 8.3 模板例子
        • templates/common目录下创建 header.html
        • templates/common目录下创建 footer.html
        • 在其他文件中,使用模板内容

背景

  • 视图解析:Spring Boot默认不支持 JSP,但确实可以通过额外配置用上JSP。
  • 不过强行用JSP已经脱离了Spring Boot易配置、快速开发的初衷。如果可能,应避免使用 JSP。所以需要引入第三方模板引擎技术实现页面渲染。
  • Spring Boot支持FreeMarker、Groovy、Thymeleaf和Mustache四种模板解析引擎,并对以上模板引擎做了自动配置支持。
  • Spring Boot 中推荐使用 Thymeleaf 作为模板引擎,因为 Thymeleaf 提供了完美的 Spring MVC 支持。
  • SpringBoot 为 Thymeleaf 提供自动配置,因此 Thymeleaf 可以与 Spring Boot 完美整合

Thymeleaf

简介

  • Thymeleaf 的主要目标是为您的开发工作流程带来优雅的自然模板:HTML可以在浏览器中正确显示,也可以作为静态原型工作,从而加强开发团队的协作。
  • Thymeleaf 是一个流行的模板引擎,该模板引擎采用 Java 语言开发
    模板引擎是一个技术名词,是跨领域跨平台的概念,在 Java 语言体系下有模板引擎,在C#、PHP 语言体系下也有模板引擎,甚至在 JavaScript 中也会用到模板引擎技术,Java 生态下的模板引擎有 Thymeleaf 、Freemaker、Velocity、Beetl(国产) 等。
  • Thymeleaf 对网络环境不存在严格的要求,既能用于 Web 环境下,也能用于非 Web 环境下。在非 Web 环境下,他能直接显示模板上的静态数据;在 Web 环境下,它能像 Jsp 一样从后台接收数据并替换掉模板上的静态数据。它是基于 HTML 的,以 HTML 标签为载体,
  • Thymeleaf 要寄托在 HTML 标签下实现。
  • Spring Boot 集成了 Thymeleaf 模板技术,并且 Spring Boot 官方也推荐使用 Thymeleaf 来替代 JSP 技术,Thymeleaf 是另外的一种模板技术,它本身并不属于 Spring Boot,Spring Boot只是很好地集成这种模板技术,作为前端页面的数据展示,在过去的 Java Web 开发中,我们往往会选择使用 Jsp 去完成页面的动态渲染,但是 jsp 需要翻译编译运行,效率低
  • Thymeleaf官网:https://www.thymeleaf.org/
  • Thymeleaf 官方手册:https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html

在这里插入图片描述

Thymeleaf的特征

  1. 动静结合: Thymeleaf可以让美工在浏览器查看页面的静态效果,也可以让程序员在服务器查看带数据的动态页面效果。浏览器解释HTML时会忽略未定义的标签属性,所以 Thymeleaf的模板可以静态地运行;当有数据返回到页面时,Thymeleaf 标签会动态地替换掉静态内容,使页面动态显示。
  2. 开箱即用: 它提供标准和Spring标准两种方言,可以直接套用模板实现JSTL、 OGNL表达式效果。
  3. 国际化的支持: Thymeleaf 提供Spring标准方言和一个与 SpringMVC 完美集成的可选模块,快速实现表单绑定、属性编辑器、国际化等功能。
  4. 与SpringBoot完美整合: SpringBoot提供了Thymeleaf的自动配置,设置了视图解析器,可以像以前操作jsp一样来操作Thymeleaf。代码几乎没有任何区别,就是在模板语法上有区别。

模板引擎是什么

  • 模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档。
  • 模板引擎不属于特定技术领域,它是跨领域跨平台的概念。在asp下有模板引擎,在PHP下也有模板引擎,在C#下也有,甚至JavaScript、WinForm开发都会用到模板引擎技术。
  • 常见的模板引擎都包含以下几个概念:数据(Data)、模板(Template)、模板引擎(Template Engine)和结果文档(Result Documents)。
    在这里插入图片描述

代码示例

1.引入依赖

主要是spring-boot-starter-thymeleaf依赖

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.2</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter-test</artifactId>
            <version>2.2.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

2.修改配置文件,添加Thymeleaf的配置信息

开发阶段关闭缓存

server:
  port: 9999
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/smbms?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  thymeleaf:
    cache: false # 关闭缓存,方便调试
    suffix: .html
    prefix: classpath:/templates/
    mode: HTML

mybatis:
  mapper-locations: classpath:mapper/*.xml

在这里插入图片描述

3.编写HTML模板文件

  • Spring Boot默认的模板文件存放的位置为“classpath:/templates/”,
  • Spring Boot默认的静态文件路径为”classpath:/static/”,可以存放CSS、JS文件等模板公用的静态文件。
  • 添加index.html,并导入Thymeleaf的名称空间<html lang="en" xmlns:th="http://www.thymeleaf.org">,才能使用Thymeleaf的语法和模板功能
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
<h1>首页</h1>
<hr>
    <h1>Hello,<span th:text="${who}"></span></h1>
<hr>
</body>
</html>

4.编写控制器,返回ModelAndView,进行视图渲染

package cn.smbms.controller;
import cn.smbms.pojo.User;
import cn.smbms.service.UserService;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;

/**
 * @author: zjl
 * @datetime: 2024/5/6
 * @desc: 
 */
@Controller
public class IndexController {
    @Resource
    private UserService userService;
    @RequestMapping("/index")
    public String index(Model model){
        model.addAttribute("who","周杰伦");
        return "index";
    }
}

Thymeleaf语法

1.常用标签/属性

大部分属性和 html 的一样,只不过前面加了一个 th 前缀。 加了 th 前缀的属性,是经过模版引擎处理的。

标签名用途示例
th:text显示控制器传入的值th:text=“${userName}”
th:object显示控制器传入的对象th:object=${user}
th:action指定表单提交地址<form th:action=”@{/user/}+${user.id}”></form>
th:value替换为value的属性值<input th:value=”${user.id}” name=”id”/>
th:field绑定后台对象和表单数据<input th:field=”${userCode}” id=”userCode”/>
th:href添加链接地址<a th:href=”@{css/index.css}”>css目录</a>
th:switch支持多分支需要<th:case>的配合

1.1 th:action

  • 定义后台控制器的路径,类似<form>标签的 action 属性,主要结合 URL 表达式,获取动态变量
<form id="login" th:action="@{/login}" th:method="post">......</form>

1.2 th:method

  • 设置请求方法
<form id="login" th:action="@{/login}" th:method="post">......</form>

1.3 th:href

  • 定义超链接,主要结合 URL 表达式,获取动态变量
<a th:href="@{/query/student}">相对地址没有传参数</a>

1.4 th:src

  • 用于外部资源引入,比如<script>标签的 src 属性,<img>标签的 src 属性,常与@{}表达式结合使用
  • 在 SpringBoot 项目的静态资源都放到 resources 的 static 目录下,放到 static 路径下的内容,写路径时不需要写上 static
<script type="text/javascript" th:src="@{/js/jquery-3.4.1.js}"></script>

1.5 th:text

  • 用于文本的显示,该属性显示的文本在标签体中
  • 如果是文本框,数据会在文本框外显示,要想显示在文本框内,使用 th:value
<input type="text" id="realName" name="reaName" th:text="${realName}">

1.6 th:style

  • 设置样式
<a th:onclick="'fun1('+${user.id}+')'" th:style="'color:red'">点击我</a>

1.7 th:each

  • 这个属性非常常用,比如从后台传来一个对象集合那么就可以使用此属性遍历输出
  • 它与JSTL 中的<c: forEach>类似,此属性既可以循环遍历集合,也可以循环遍历数组及 Map.
1.7.1 循环 List
<div th:style="'margin-left: 350px'">
 <p>在一个 div 中循环 p 标签</p>
 <div >
 <p th:each="str,strSt:${strlist}" th:text="${str}"></p>
 </div>
 <br/>
<div th:each="u:${userList}">
<p th:text="${uStat.count}+'/'+${uStat.size}"></p>
 <p th:text="${u.id}"></p>
 <p th:text="${u.name}"></p>
 <p th:text="${u.sex}"></p>
  <p th:text="${u.age}"></p>
 </div>
</div>
语法说明

th:each="user, iterStat : ${userlist}"中的 ${userList} 是后台传过来的集合

  • user
    • 定义变量,去接收遍历${userList}集合中的一个数据
  • iterStat
    • ${userList} 循环体的信息
  • 其中 user 及 iterStat 自己可以随便取名
  • interStat 是循环体的信息,通过该变量可以获取如下信息
    • index: 当前迭代对象的 index(从 0 开始计算)
    • count: 当前迭代对象的个数(从 1 开始计算)这两个用的较多
    • size: 被迭代对象的大小
    • current: 当前迭代变量
    • even/odd: 布尔值,当前循环是否是偶数/奇数(从 0 开始计算)
    • first: 布尔值,当前循环是否是第一个
    • last: 布尔值,当前循环是否是最后一个
  • 注意:循环体信息 interStat 也可以不定义,则默认采用迭代变量加上 Stat 后缀,即
    userStat
1.7.2 循环 Map
<p>普通Map封装的对象</p>
 <div th:each="m,mSt:${users}">
 <p th:text="${mSt.count}"></p>
 <p th:text="${m.key}"> </p>
 <p th:text="${m.value.id}"></p>
 <p th:text="${m.value.name}"></p>
 <br/>
 </div>
<p>list-map</p>
 <div th:each="ul:${listmap}">
 <div th:each="um:${ul}">
 <p th:text="${um.key}"></p>
 <p th:text="${um.value.id}"></p>
 <p th:text="${um.value.name}">姓名是</p>
 </div>

1.8 条件if

  • 语法:th:if=”boolean 条件” , 条件为 true 显示体内容
  • th:unless 是 th:if 的一个相反操作
<p th:if="${sex =='m'}">
 性别是 男
</p>
<p th:unless="${sex == 'f'}">
 性别是女
</p>
<p th:if="${isLogin}">
 用户已经登录
</p>
<p th:if="${age > 50}">
 年龄是大于 50
</p>
<p th:if="5>0">
 5>0
</p>
<!-- 空字符串是 true-->
<p th:if="${name}">
 name 是 ‘’
</p>
        <tr th:if="${#lists.isEmpty(userList)}">
            <td colspan="5">暂无数据</td>
        </tr>
        <tr th:unless="${#lists.isEmpty(userList)}" th:each="user: ${userList}">
            <td th:text="${userStat.count}"></td>
            <td th:text="${user.userCode}"></td>
            <td th:text="${user.userName}"></td>
            <td th:text="${user.userRole}"></td>
            <td th:text="${user.address}"></td>
        </tr>
        </tbody>

1.9 switch,case 判断语句

  • 语法:类似 java 中的 switch,case
<div th:switch="${sex}">
 <p th:case="m">显示男</p>
 <p th:case="f">显示女</p>
 <p th:case="*">未知</p>
</div>
  • 一旦某个 case 判断值为 true,剩余的 case 则都当做 false,“*”表示默认的case,前面的 case 都不匹配时候,执行默认的 case

1.10 th:inline

  • th:inline 有三个取值类型 (text, javascript 和 none)
1.10.1 内联text
  • 可以让 Thymeleaf 表达式不依赖于 html 标签,直接使用内敛表达式[[表达式]]即可获取动态数据,要求在父级标签上加 th:inline = “text”属性
    <div th:inline="text">
     姓名是:[[${name}]] <br/>
     登录了吗:[[${isLogin}]]
    </div>
    <br/>
    <!--不用加入 th:inline='text'-->
    <div>
     姓名是:[[${name}]] <br/>
     登录了吗:[[${isLogin}]]<br/>
     性别:[[${sex}]]
    </div>
    
1.10.2 内联javaScript
  • 可以在 js 中,获取模版中的数据。
  • 在上面的模版页面中,增加
<button onclick="fun()">单击按钮</button>
<script type="text/javascript" th:inline="javascript">
 var name = [[${myuser.name}]];
 var id = [[${myuser.id}]];
 function fun() {
 alert("click 用户是"+name+",他的 id 是"+id);
 }
</script>

2.表达式

表达式是在页面获取数据的一种 thymeleaf 语法。类似 ${key}

表达式名字语法用途
变量取值${…}获取请求域、session域、对象等值
选择变量*{…}获取上下文对象值
获取消息值#{…}获取国际化等值
链接@{…}生成链接
片段表达式~{…}引入公共页面片段

2.1 标准变量表达式

  • 注意:th:text=“” 是 Thymeleaf 的一个属性,用于文本的显示
  • 语法: ${key}
  • 说明:
    • 标准变量表达式用于访问容器(tomcat)上下文环境中的变量,功能和 EL 中的 ${} 相同。
    • Thymeleaf 中的变量表达式使用 ${变量名} 的方式获取 Controller 中 model 其中的数据。也就是 request 作用域中的数据。
    • 模版文件(html)修改后,可以使用 idea—Build 菜单-Recompile 编译文件。重新 Recompile即可生效。

2.2 选择变量表达式

  • 语法:*{key}
  • 说明:需要配和 th:object 一起使用。选择变量表达式,也叫星号变量表达式,使用 th:object 属性来绑定对象,选择表达式首先使用 th:object 来绑定后台传来的对象,然后使用 * 来代表这个对象,后面 {} 中的值是此对象中的属性。
  • 选择变量表达式 *{…} 是另一种类似于标准变量表达式${…} 表示变量的方法
  • 选择变量表达式在执行时是在选择的对象上求解,而${…}是在上下文的变量 model 上求解
<div style="margin-left: 350px">
 <p>学习选择表达式</p>
 <div th:object="${myuser}">
 <p th:text="*{id}">id</p>
 <p th:text="*{name}">name</p>
 <p th:text="*{sex}">sex</p>
 <p th:text="*{age}">age</p>
 </div>
 <p th:text="*{myuser.name}"></p>
</div>

2.3 链接表达式(URL 表达式)

  • 语法:@{链接 url}
  • 说明:主要用于链接、地址的展示,可用于<script src=“…”>、<link href=“…”>、<a href=“…”>、<form action=“…”>、<img src=“”>等,可以在 URL 路径中动态获取数据
<div style="margin-left: 350px">
 <p>链接表达式</p>
 <p>链接到绝对地址</p>
 <a th:href="@{http://www.baidu.com}">百度</a>
 <br/>
 <br/>
 <p>链接到相对地址</p>
 <a th:href="@{/query/student}">相对地址没有传参数</a>
 <br/>
 <br/>
 <p>链接到相对地址,传参数方式 1</p>
 <a th:href="@{'/query/student?id='+${stuId}}">相对地址传参数方式1</a>
 <br/>
 <br/>
 <p>链接到相对地址,传参数方式 2,推荐方式</p>
 <a th:href="@{/find/school(id=${stuId},name='lisi')}">相对地址传参数方式 2</a>
</div>
//链接表达式
@GetMapping("/thy/link")
public String link(Model model){
 model.addAttribute("stuId",1001);
 return "03-link";
}
@GetMapping("/query/student")
@ResponseBody
public String query(Integer id){
 return "查询学生 id="+id;
}
@GetMapping("/find/school")
@ResponseBody
public String query2(Integer id, String name){
 return "查询 2,id="+id+",姓名="+name;
}

3.字面量

Controller 增加方法:

//字面量
@GetMapping("/thy/text")
public String text(Model model){
 model.addAttribute("sex","m");
 model.addAttribute("isLogin",true);
 model.addAttribute("age",20);
 model.addAttribute("name",null);
 model.addAttribute("city","郑州");
 model.addAttribute("myuser",new SysUser(1005,"张三","f",23));
 return "index";
}

3.1 文本字面量

用单引号’…'包围的字符串为文本字面量

<p th:text="'城市是'+${city}+' 用户登录'+${isLogin}"></p>

3.2 数字字面量

<p th:if="${age > 10}"> age > 10 </p>
<p th:if="20 > 5">20 大于 5</p>

3.3 boolean字面量

<p th:if="${isLogin == true}">用户登录了</p>

3.4 null字面量

<p th:if="${name == null}"> name 是 null </p>

4. 字符串连接

<p>字符串的连接,1 使用'';2 使用|字符串内容|</p>
<p th:text="'城市是'+${city}+' 用户登录'+${isLogin}"></p>
<p th:text="|城市是${city}用户登录${isLogin}|"></p> 

5.运算符

5.1 算术运算:

  • + , - , * , / , %

5.2 关系比较:

  • > , < , >= , <= ( gt , lt , ge , le )
  • 相等判断:== , != ( eq , ne )
<p th:if="${age > 10}"> age > 10 </p>
<p th:if="20 > 5">20 大于 5</p>
<p th:text="${sex =='m' ? '男':'女'}"></p>
<p th:text="${sex =='m' ? (isLogin?'男已经登录':'男的没有登录'):'女'}"></p>

5.3 布尔运算符:

  • and,or, not,!

5.4 条件运算符:

  • if-then: (if) ? (then)
  • if-then-else: (if) ? (then) : (else)
  • Default: (value) ?: (defaultvalue)

6.Thymeleaf 基本对象

  • 模板引擎提供了一组内置的对象,这些内置的对象可以直接在模板中使用,这些对象由#号开始引用,我们比较常用的内置对象
  • 创建Controller
//模版中基本对象
@GetMapping("/thy/baseObject")
public String baseObject(Model model, HttpServletRequest request, HttpSession session ){
 request.setAttribute("reqdata","request 中的数据");
 request.getSession().setAttribute("sessdata","session 中数据");
session.setAttribute("loginname","zhangsan");
 return "index";
}
  • #request 表示 HttpServletRequest
  • #session 表示 HttpSession 对象
  • session 对象,表示 HttpSession 对象
<div th:style="'margin-left: 350px'">
<p th:text="${#request.getAttribute('reqdata')}">request 作用域</p>
 <p th:text="${#request.getServerName()}"></p>
 <p th:text="${#request.getServerPort()}"></p>
 <p th:text="${#request.getServletPath()}"></p>
 <br/>
<p th:text="${#session.getAttribute('sessdata')}">session 中数据</p>
<p>处理#request,#session,session</p>
<p th:text="${#request.getServerName()}"></p>
<p th:text="${#request.getServerPort()}"></p>
<p th:text="${#request.getRequestURL()}"></p>
<p th:text="${#request.getRequestURI()}"></p>
<p th:text="${#request.getQueryString()}"></p>
<br/>
<br/>
<p th:text="${#session.getAttribute('loginname')}"></p>
<p th:text="${session.loginname}"></p>
</div>

7.Tymeleaf 内置工具类对象

  • 模板引擎提供的一组功能性内置对象,可以在模板中直接使用这些对象提供的功能方法
  • 工作中常使用的数据类型,如集合,时间,数值,可以使用 Thymeleaf 的提供的功能性对象来处理它们
  • 内置功能对象前都需要加#号,内置对象一般都以 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: 对数组或集合创建聚合的实用方法

示例(后台)

@GetMapping("/thy/utilObject")
public String utilObject(Model model, HttpSession session){
 model.addAttribute("mydate",new Date());
 model.addAttribute("mynum",26.695);
 model.addAttribute("mystr","bjpowernode");
 List<String> mylist = Arrays.asList("a","b","c");
 model.addAttribute("mylist",mylist);
 //model.addAttribute("mylist",null);
 session.setAttribute("loginname","zhangsan");
 Dog dog = new Dog();
 dog.setName("二哈");
 Cat cat = new Cat();
 cat.setName("英短");
 Zoo zoo = new Zoo();
 zoo.setCat(cat);
 //zoo.setDog(dog);
 zoo.setDog(null);
 model.addAttribute("zoo",zoo);
 return "index";
}

示例(前端)

<p th:text="${#dates.format(mydate,'yyyy-MM-dd')}"></p>
<p th:text="${#dates.format(mydate,'yyyy-MM-dd HH:mm:ss')}"></p>
<p th:text="${#dates.year(mydate)}"></p>
<p th:text="${#dates.month(mydate)}"></p>
<p th:text="${#dates.createNow()}" />
<br/>
<br/>
<p th:text="${#numbers.formatCurrency(mynum)}"></p>
<p th:text="${#numbers.formatDecimal(mynum,5,2)}"></p>
<br/>
<p>处理@#strings</p>
<p th:text="${#strings.toUpperCase(mystr)}"></p>
<p th:text="${#strings.indexOf(mystr,'power')}"></p>
<p th:text="${#strings.substring(mystr,2,5)}"></p>
<p th:text="${#strings.concat(mystr,'----java 开发')}"></p>
<br/>
<br/>
<p>处理#lists</p>
<p th:text="${#lists.isEmpty(mylist)}"></p>
<p th:if="!${#lists.isEmpty(mylist)}" ></p>
<p th:text="${#lists.size(mylist)}"></p>
<p>空值</p>
<p th:text="${zoo?.dog?.name}"></p>

8.模板

  • 自定义模板是复用的行为。可以把一些内容,多次重复使用

8.1定义模板

  • 语法:th:fragment=“top” , 定义摸模板,自定义名称是 top。例如:
<div th:fragment="top">
 <p>北大青鸟课工场</p>
 <p>kgc.cn</p>
</div>

8.2 引用模板

  • 语法:引用模板 ~{ templatename :: selector} 或者 templatename :: selector。例如:
<div th:insert="~{head :: top}"></div>
<div th:include="head :: top"></div>

8.3 模板例子

templates/common目录下创建 header.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
 <meta charset="UTF-8">
</head>
<body>
 <!--定义模板, 就是一段页面代码-->
 <div th:fragment="top">
 <p>XX系统首页</p>
 <p>www.baidu.com</p>
 </div>
</body>
</html>
templates/common目录下创建 footer.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<div th:fragment="foot">
  footer
  www.baidu.com @copy; 百度 2024
</div>
</body>
</html>
在其他文件中,使用模板内容
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div th:replace="common/head::top"></div>
<h1>hello,<span th:text="${session.loginUser.userName}"></span></h1>
<a th:href="@{/user/list}">用户列表</a>
<a th:href="@{/user/list(userName=${session.loginUser.userName},userRole=1)}">用户列表2</a>
</body>
<div th:replace="common/footer::foot"></div>
</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/606793.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot 使用Outlook邮箱发送邮件

目录 一、开启Outlook设置 二、依赖 三、配置文件 四、代码调用 一、开启Outlook设置 开启设置如图&#xff1a; 二、依赖 <!-- 邮箱依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-mai…

Java -- (part25)

一.Junit单元测试 1.概述 是一个单元测试框架,可以代替main方法去执行其他的方法 2.使用 a.导入jar包 b.注解 Test:单独执行一个方法 Before:在Test之前执行,有几个Test就有几个Before After:在Test之后执行,有几个Test就有几个After 二.类的加载机制 1.类的加载时机…

七款好用的上网行为管理软件推荐 |有没有好用的上网行为管理系统

七款好用的上网行为管理软件推荐 |有没有好用的上网行为管理系统 员工上班刷视频&#xff01; 员工上班炒股&#xff01; 员工上班干副业&#xff01; 碰见这种情况怎么办&#xff1f;当然是用电脑监控软件来监视员工的一举一动了&#xff0c;那么这样的软件有哪些呢&#…

充电桩测试:选择适合的负载箱

随着电动汽车的普及&#xff0c;充电桩的需求也在不断增加。为了保证充电桩的性能和安全&#xff0c;对其进行测试是非常重要的。在充电桩测试过程中&#xff0c;选择合适的负载箱是关键。本文将介绍如何选择合适的负载箱进行充电桩测试。 在进行充电桩测试之前&#xff0c;首先…

思腾合力受邀参加VALSE 2024视觉与学习青年学者研讨会

在充满学术氛围的五月&#xff0c;思腾合力荣幸受邀参加了于2024年5月5-7日在重庆举行的第十四届VALSE大会。作为视觉与学习领域的顶级交流平台&#xff0c;VALSE大会每年都吸引着全国专家与学者的目光。 本次大会不仅延续了往届的高水平学术研讨&#xff0c;还进一步拓宽了研究…

【CTF-Crypto】RSA-选择明密文攻击 一文通

RSA&#xff1a;选择明密文攻击 关于选择明/密文攻击&#xff0c;其实这一般是打一套组合拳的&#xff0c;在网上找到了利用的思路&#xff0c;感觉下面这个题目是真正将这个问题实现了&#xff0c;所以还是非常棒的一道题&#xff0c;下面先了解一下该知识点&#xff1a;(来自…

【可实战】被测需求理解(需求文档是啥样的、从哪些角度进行需求评审、需求分析需要分析出哪些内容、如何提高需求分析能力)

产品人员会产出一个需求文档&#xff0c;然后组织一个需求的宣讲。测试人员的任务就是在需求宣讲当中&#xff0c;分析需求有没有存在一些问题&#xff0c;然后在需求宣讲结束之后通过分析需求文档&#xff0c;分析里面的测试点并预估一个排期。 一、需求文档是什么样的&#x…

SmartEDA电路仿真软件风靡教育圈:揭秘其背后的魅力所在

在当今的电子信息时代&#xff0c;随着科技的飞速发展&#xff0c;电路设计与仿真软件在教育领域的应用越来越广泛。特别是SmartEDA这款电路仿真软件&#xff0c;以其强大的功能和直观易用的操作界面&#xff0c;赢得了众多教师的青睐。那么&#xff0c;究竟是什么原因让SmartE…

给汉字注音可以主要拼音不要声调吗?这两个注音小技巧你一定会需要

一&#xff0c;前言 在中文学习中&#xff0c;拼音是一种非常重要的工具&#xff0c;它帮助学习者正确地发音和理解汉字。然而&#xff0c;在拼音的使用中&#xff0c;一个常见的问题是是否应该包含声调。有些人认为&#xff0c;只要拼音中有声母和韵母&#xff0c;就可以准确…

如何使用client-go构建pod web shell

代码示例及原理 原理是利用websocket协议实现对pod的exec登录&#xff0c;利用client-go构造与远程apiserver的长连接&#xff0c;将对pod容器的输入和pod容器的输出重定向到我们的io方法中&#xff0c;从而实现浏览器端的虚拟终端的效果消息体结构如下 type Connection stru…

苏州金龙何以成为塞尔维亚中国客车第一品牌?研发向上服务助力!

5月7日至8日&#xff0c;一场举世瞩目的会晤在塞尔维亚举行。作为塞尔维亚中国客车第一品牌&#xff0c;苏州金龙海格客车也为当地民众绿色公共出行提供了“中国力量”。 目前&#xff0c;苏州金龙海格客车在塞尔维亚保有量近200台&#xff0c;是在塞尔维亚保有量最大的中国客车…

鸿蒙OpenHarmony开发板【快速入门】大合集

快速入门 快速入门概述 基于IDE入门 搭建开发环境 搭建Windows环境搭建Ubuntu环境配置远程访问环境创建工程并获取源码 轻量系统&#xff08;基于Hi3861开发板&#xff09; 编写“Hello World”程序编译烧录运行 小型系统&#xff08;基于Hi3516开发板&#xff09; 编写“Hell…

上海计算机学会2023年8月月赛C++丙组T2下降幂多项式

题目描述 x 的 k 次下降幂定义为 x 的下降幂多项式是由 x 的一组下降幂及系数组成的算式&#xff1a; 给定下降幂多项式 f(x) 的系数 an​,an−1​,⋯,a0​ 与一个值 m&#xff0c;请计算f(m)mod1,000,000,007。 输入格式 第一行&#xff1a;两个整数 n 与 m第二行&#xff…

数据库加密数据模糊匹配查询技术方案

文章目录 前言沙雕方案内存加载解密密文映射表 常规做法实现数据库加密算法参考 分词组合加密&#xff08;推荐&#xff09; 超神方案总结个人简介 前言 在数据安全性和查询效率之间找到平衡是许多数据管理系统所面临的挑战之一。特别是在涉及加密数据的情况下&#xff0c;如何…

数据结构之单链表的基本操作

目录 一.定义一个单链表 二.实现基本操作 1&#xff09;链表的打印 2&#xff09;链表的尾插 3&#xff09;链表的头插 4&#xff09;链表的尾删 5&#xff09;链表的头删 6&#xff09; 链表的查找 7&#xff09;在指定位置之前插入数据 8&#xff09;在指定位置之…

Android 11 输入系统之InputDispatcher和应用窗口建立联系

InputDispatcher把输入事件传给应用之前&#xff0c;需要和应用窗口建立联系&#xff0c;了解了这个过程&#xff0c;就清楚了APP进程和InputDispatcher线程也就是SystemServer进程之间是如何传输数据了 我们向窗口addView的时候&#xff0c;都会调用到ViewRootImpl的setView方…

电脑文件加密软件有哪些?口碑、安全性最好的文件加密软件

某企业的一位员工因不慎将包含敏感客户数据的电脑丢失&#xff0c;导致企业面临巨大的法律风险和经济损失。 这一事件凸显了电脑文件加密的必要性。 如果该企业事先采用了文件加密软件对敏感数据进行保护&#xff0c;即使电脑丢失&#xff0c;攻击者也无法轻易获取到文件内容…

eve 导入linux

mkdir /opt/unetlab/addons/qemu/linux-centos7 cd /opt/unetlab/addons/qemu/linux-centos7 上传hda.qcow2 /opt/unetlab/wrappers/unl_wrapper -a fixpermissions Linux images - (eve-ng.net) Due to very high demand of this section and problems with how to crea…

图像处理(二)

图像处理&#xff08;2&#xff09; 裁剪图片 from skimage import io,dataiimg io.imread(rD:\工坊\图像处理\十个勤天2.png)roiiimg[50:150,120:200,:]io.imshow(roi) 运行结果&#xff1a; 将图片进行二值化 from skimage import io,data,colorimg io.imread(r"…

在数据分析中所需要运用到的概率论知识

数据分析 前言一、总体二、样本三、统计抽样抽取的基本准则 四、随机抽样抽签法随机数法 五、分层抽样六、整群抽样七、系统抽样八、统计参数常用的分布函数参数 九、样本统计量十、样本均值和样本方差十一、描述样本集中位置的统计量样本均值样本中位数样本众数 十二、描述样本…