【SpringBoot整合系列】SpringBoot整合Thymeleaf

news/2024/5/20 10:50:32

目录

  • 背景
  • 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.Driverurl: jdbc:mysql://localhost:3306/smbms?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghaiusername: rootpassword: 123456thymeleaf:cache: false # 关闭缓存,方便调试suffix: .htmlprefix: classpath:/templates/mode: HTMLmybatis: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 {@Resourceprivate 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">footerwww.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.mrgr.cn/p/77228531

相关文章

Qt常用基础控件总结

一、按钮部件 按钮部件共同特性 Qt 用于描述按钮部件的类、继承关系、各按钮的名称和样式,如下图: 助记符:使用字符"&“可在为按钮指定文本标签时设置快捷键,在&之后的字符将作为快捷键。比如 “A&BC” 则 Alt+B 将成为该按钮的快捷键,使用”&&qu…

React文本溢出组件封装以及高亮提示

React文本溢出组件封装以及高亮提示Abbr 组件:使用场景:当我们需要设置支持最大行数时进行省略展示 当我们需要设置支持设置超过多少字符进行省略展示 当我们需要设置支持关键字高亮展示(有点问题,当关键字被裁剪成...之后,就无法高亮) 当我们需要支持忽略大小写高亮 当我…

边缘智能网关P1600,智慧林业的得力助手

随着科技的不断发展&#xff0c;人工智能、物联网、大数据等先进技术在林业领域的应用日益广泛&#xff0c;为林业管理带来了革命性的变革。智慧林业的核心目标是实现林业资源的数字化、网络化和智能化&#xff0c;从而提高林业管理的效率和水平。边缘智能网关P1600作为一种新型…

AlmaLinux 9.4 正式版发布 - RHEL 二进制兼容免费发行版

AlmaLinux 9.4 正式版发布 - RHEL 二进制兼容免费发行版AlmaLinux 9.4 正式版发布 - RHEL 二进制兼容免费发行版 由社区提供的免费 Linux 操作系统,RHEL 二进制兼容发行版 请访问原文链接:AlmaLinux 9.4 正式版发布 - RHEL 二进制兼容免费发行版,查看最新版。原创作品,转载…

cc6链:绕过cc1的jdk限制

这里回到LazyMap,LazyMap的get方法可以触发后续的rce为什么cc1有jdk版本限制 JDK中的AnnotationInvocationHandler的readObject更新了,所以cc1用不了 但是前面的部分还是存在的,只要我们找到一个新的入口就还是能执行命令 这里回到LazyMap,LazyMap的get方法可以触发后续的r…

第二届数信杯南区wp-easyJava

第二届数信杯南区easyJavawriteup easyJava 用Eclipse Memory Analyzer进行分析,利用OQL查找字符串这里要写正则表达式:我写了\\u.*意思是找unicode字符串,因为这里的中文都做了unicode编码搜索到这么一个字符串列表,转码——红色框框里的是还原后的内容。如下: 想跟你说一…

分布式链路追踪工具Sky walking详解

1&#xff0c;为什么要使用分布式链路追踪工具 随着分布式系统和微服务架构的出现&#xff0c;且伴随着用户量的增加&#xff0c;项目的体量变得十分庞大&#xff0c;一次用户请求会经过多个系统&#xff0c;不同服务之间调用关系十分复杂&#xff0c;一旦一个系统出现错误都可…

建发弘爱 X 袋鼠云:加速提升精细化、数字化医疗健康服务能力

厦门建发弘爱医疗集团有限公司(简称“建发弘爱”)创立于2022年,是厦门建发医疗健康投资有限公司的全资子公司,专业从事医疗健康领域的医疗服务。 建发弘爱通过医疗、健康及产业服务三大板块,为百姓提供医疗和健康全生命周期解决方案。以医疗机构为核心,管理及运营弘爱医院…

Linux-进程调度器

1. 前言 在计算机中&#xff0c;进程的数量远多于cpu的数量&#xff0c;所以就存在&#xff0c;多个进程抢占一个cpu的情况&#xff0c;所以就需要一套规则&#xff0c;决定这些进程被处理的顺序&#xff0c;这就叫做进程调度。 在我的简单理解下&#xff0c;其实就是把进程放…

删除单向链表中数据最小的结点

删除单向链表中数据最小的结点(1)算法的基本设计思想 要找到链表中数据最小的结点,可以使用4指针法。具体步骤如下:定义4个指针,分别命名为MinNodeprev、MinNode、CurrentNodePrev、CurrentNode,MinNodeprev、CurrentNodePrev指向链表的头结点,MinNode、CurrentNode指向…

leetcode 1235

leetcode 1235 代码 class Solution { public:int jobScheduling(vector<int>& startTime, vector<int>& endTime, vector<int>& profit) {int n startTime.size();vector<vector<int>> jobs(n);for(int i0; i<n; i){jobs[i] …

RabbitMQ保证消息的可靠性

一、背景 消息丢失&#xff1a;下图是消息从生产者发送到消费者接收的关系图。通过图片可以看出&#xff0c;消息在生产者、MQ、消费者这三个环节都有可能丢失。 1.1 生产者丢失 生产者发送消息时连接MQ失败生产者发送消息到达MQ后未找到Exchange生产者发送消息到达MQ的Exc…

Java-线程-线程池

0.背景参考资料:Java线程池实现原理及其在美团业务中的实践在 Java 早期,每次创建线程时,都要涉及到线程的创建、销毁以及资源管理,这对于系统的性能和资源利用率是一种浪费。 因此,Java 提供了线程池的概念,以提高线程的管理效率和性能。资源管理优化:传统的线程创建和…

vue2项目升级到vue3经历分享4

后端重构&#xff0c;如果接口做好抽象封装&#xff0c;只需要考虑jar之间的兼容性问题&#xff0c;jdk版本不变&#xff0c;基本不用做太大的调整&#xff0c;但是前端就不一样&#xff0c;除了vue框架本身&#xff0c;css的调整&#xff0c;改起来更是让人头疼。前面写了vue2…

8.2版本Web端移动开发调试强制跳转新移动框架

解决方案: Common.config文件中增加配置项 <add key="MobileLoginType" value="1" /> 如下图其他注意事项: 没有配置MobileLoginType属性 或 MobileLoginType = "" 或 MobileLoginType = 2 都会执行重定向 MobileLoginType = 3 系…

SQL 基础 | UNION 用法介绍

在SQL中&#xff0c;UNION操作符用于合并两个或多个SELECT语句的结果集&#xff0c;形成一个新的结果集。 使用UNION时&#xff0c;合并的结果集列数必须相同&#xff0c;并且列的数据类型也需要兼容。 默认情况下&#xff0c;UNION会去除重复的行&#xff0c;只保留唯一的行。…

cordova build android 下载gradle太慢

一、 在使用cordova run android / cordova build android 的时候 gradle在线下载 对于国内的链接地址下载太慢。 等待了很长时间之后还会报错。 默认第一次编译在线下载 gradle-7.6.1-all.zip 然后解压缩到 C:\Users\Administrator\.gradle 文件夹中,下载慢导致失败。 二…

【软件工程】需求分析

目录 前言需求分析需求获取UML概述用例图用例图的组成用例图中的符号和含义包含的两种使用场景 用例图补充&#xff1a;“系统”用例模型建模确定系统参与者确定系统用例 用例文档用例文档组成部分 活动图组成元素初始节点和终点活动节点转换决策与分支、合并分岔与汇合 类图类…

Java面试八股文(SpringCloud篇)

****************************************************