【SpringBoot整合系列】SpringBoot整合Thymeleaf

news2024/9/24 21:24:39

目录

  • 背景
  • 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>

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java 函数式编程 的基础使用2-BiConsumer

1、创建函数时&#xff0c;确定函数的参数类型和具体操作。 2、使用accept接收函数参数&#xff0c;并执行函数操作。 public class MyBiConsumer {public static void main(String[] args) {BiConsumer<String, Integer> printNameAndAge (param1, param2) -> {Sys…

Android中TabLayout与ViewPager结合使用生命周期详解

博主前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住也分享一下给大家&#xff0c; &#x1f449;点击跳转到教程 效果 使用的布局如下&#xff1a; <?xml version"1.0" encoding"utf-8"?> …

HDU - 3988 Harry Potter and the Hide Story 题解 数论

Harry Potter and the Hide Story 传送门&#xff08;建议到 vjudge 上去提交&#xff09; iSea is tired of writing the story of Harry Potter, so, lucky you, solving the following problem is enough. Input The first line contains a single integer T T T, indic…

黄历择日网php程序源码/日历老皇历万年历带免登录发布模块

黄历择日网php程序源码/日历老皇历万年历带免登录发布模块&#xff0c;不调用接口的&#xff0c;带数据库带黄历算法类&#xff0c;完整版免授权&#xff0c;完全开源程序&#xff0c;可二开&#xff01; 演示地址&#xff1a; https://s22.21sq.top/ 手机端地址&#xff1a…

等保建设技术建议书(Word原件)

1信息系统详细设计方案 1.1安全建设需求分析 1.1.1网络结构安全 1.1.2边界安全风险与需求分析 1.1.3运维风险需求分析 1.1.4关键服务器管理风险分析 1.1.5关键服务器用户操作管理风险分析 1.1.6数据库敏感数据运维风险分析 1.1.7“人机”运维操作行为风险综合分析 1.2…

Shiro-Action:基于Shiro的RESTful权限管理系统

摘要&#xff1a; 随着RESTful API的广泛应用&#xff0c;对权限管理的需求也日益增长。Shiro-Action是一个基于Shiro的权限管理系统&#xff0c;专注于RESTful风格的URL授权。本文将深入探讨Shiro-Action的设计思路、技术实现以及在实际项目中的应用价值。 一、引言 RESTful…

VGA项目:联合精简帧+双fifo+sobel算法 实现VGA显示

前言&#xff1a;该项目实际上是在很多基础的小练习上合成起来的&#xff0c;例如涉及到uart&#xff08;rs232&#xff09;的数据传输、双fifo流水线操作、VGA图像显示&#xff0c;本次内容在此基础上又增添了sobel算法&#xff0c;能实现图像的边沿监测并VGA显示。 文章目录…

算法学习007-进制转换 c++递归算法实现 中小学算法思维学习 信奥算法解析

目录 C进制转换 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 七、推荐资料 C进制转换 一、题目要求 1、编程实现 小明学c有一段时间了&#xff0c;今天他想做一个进制转换的小程序&#xff0c;将十进…

如何省下5000培训费学会月薪8000的嵌入式Linux?

嵌入式底层开发无疑是一项极为关键的技术&#xff0c;它在众多嵌入式系统中都有着广泛而重要的应用。在当今科技飞速发展的时代&#xff0c;嵌入式系统已经深入到我们生活的每一个角落&#xff0c;成为了我们日常生活中不可或缺的一部分&#xff0c;这也更加凸显了嵌入式开发的…

【Linux极简教程】常见实用命令不断更新中......

【Linux极简教程】常见实用命令不断更新中...... 常见问题1.Waiting for cache lock: Could not get lock /var/lib/dpkg/lock. It is held by process xxxx(dpkg) 常见问题 1.Waiting for cache lock: Could not get lock /var/lib/dpkg/lock. It is held by process xxxx(dp…

关于图形库

文章目录 1. 概念介绍2. 使用方法2.1 普通路由2.2 命名路由 3. 示例代码4. 内容总结 我们在上一章回中介绍了"使用get显示Dialog"相关的内容&#xff0c;本章回中将介绍使用get进行路由管理.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在本章…

stm32单片机开发五、使用I2C连接MPU6050

10轴就是3轴加速度、3轴角速度、3轴磁场强度和1个气压强度 任何一种传感器都不能获得精确且稳定的欧拉角&#xff0c;要想获得精确且稳定的欧拉角&#xff0c;就必须进行数据融合&#xff0c;把这几种传感器的数据结合起来&#xff0c;常见的数据融合算法&#xff0c;一般有互补…

可编程 IP 新星 Story Protocol 何以引领链上文艺复兴浪潮?

当前&#xff0c;随着 Web3 行业发展进入全新阶段&#xff0c;与生成式人工智能&#xff08;AIGC&#xff09;技术融合正在创造潜力新星项目。也是目前的互联网生态下&#xff0c;任何普通民众都有权利创作高质量的音乐、艺术、散文和视频内容&#xff0c;带来了用户生成内容&a…

Verilog中求两个数的差值

根据输入信号a,b的大小关系&#xff0c;求解两个数的差值&#xff1a;输入信号a,b为8bit位宽的无符号数。如果a>b&#xff0c;则输出a-b&#xff0c;如果a≤b&#xff0c;则输出b-a。 接口信号图如下&#xff1a; 代码如下&#xff1a; &#xff08;CSDN代码块不支持Veril…

去斯洛文尼亚旅游最有趣的徒步路线推荐

春天当然要去徒步呀&#xff01;斯洛文尼亚的徒步和登山小径纵横交错&#xff0c;遍布全国&#xff0c;尽管很多人首先想到的是高山地区连绵起伏的山峰&#xff0c;但实际上&#xff0c;在其他地区也有许多值得游览的徒步目的地。 ​ 这些低地地区的徒步路线将带你穿过如画的风…

【小行星数据预处理py-】

#数据的导入 import pandas as pd import numpy as np#导入EXCEL表格数据;na_values指定了将Excel文件中的空单元格转换为NaN df_excelpd.read_excel(C:/Users/galax/Desktop/MBA小行星数据/4000.xls,na_values0) #定义0为缺失值 see_datadf_excel #统计每一列的缺失值个数 pri…

可代替IRS2003的半桥栅极驱动器KP85211A 225V耐压 1A/1.5A

KP85211A是一款 225V 耐压&#xff0c;具有 1A 拉电流和 1.5A 灌电流能力的半桥栅极驱动器&#xff0c;专用于驱动功率MOSFET或IGBT。采用高压器件工艺技术&#xff0c;具有良好的电流输出及出色的抗瞬态干扰能力。可保证开关节点 VS 瞬态 -7V 情况下系统正常工作。可支持开关节…

Leetcode—706. 设计哈希映射【简单】(constexpr)

2024每日刷题&#xff08;127&#xff09; Leetcode—706. 设计哈希映射 数组实现代码 class MyHashMap { public:MyHashMap() {memset(arr, -1, sizeof(arr));}void put(int key, int value) {arr[key] value;}int get(int key) {if(arr[key] -1) {return -1;} return arr…

基于openEuler22.03 LTS环境的docker容器基础

一、说明 本文配置环境为VMware虚拟机或华为云服务器&#xff08;4核CPU&#xff0c;8 GB内存&#xff0c;40GB磁盘&#xff09;&#xff0c;OS为openEuler 22.03 LTS &#xff0c;Linux服务器要求能联网。 二、安装docker 2.1 安装docker软件包 [rootnode01 ~]# dnf -y in…

leetcode尊享面试——二叉树(python)

250.统计同值子树 使用dfs深度搜索&#xff0c;同值子树&#xff0c;要满足三个条件&#xff1a; 对于当前节点node&#xff0c;他的左子树血脉纯净&#xff08;为同值子树&#xff09;&#xff0c;右子树血脉纯净&#xff08;为同值子树&#xff09;&#xff0c;node的值等于…