springboot系列十一:Thymeleaf

news2024/12/29 8:45:15

文章目录

  • 官方文档
  • 基本介绍
  • Thymeleaf机制说明
  • Thymeleaf语法
    • 表达式
    • 运算符
    • th属性
    • 迭代
    • 条件运算
    • 使用Thymeleaf th属性需要注意点
  • Thymeleaf综合案例
    • 需求说明
    • 思路分析
    • 代码实现
  • 作业布置

在这里插入图片描述

官方文档

在线文档: https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html

离线文档: Thymeleaf离线文档

基本介绍

●Thymeleaf是什么?

1.Thymeleaf 是一个跟 Velocity, FreeMarker 类似的模板引擎, 可完全替代 JSP.

2.Thymeleaf 是一个java类库, 它是一个 xml/xhtml/html5 的模板引擎, 可以作为mvcweb应用的view层.


●Thymeleaf的优点

1.实现JSTL, OGNL的表达式效果, 语法相似, java程序员上手快.

2.Thymeleaf模板页面无需服务器渲染, 也可以被浏览器运行, 页面简洁.

3.SpringBoot支持FreeMarker, Thymeleaf, veocity.


●Thymeleaf的缺点

1.THymeleaf: Thymeleaf is a modern server-side Java template engine for both web and standalone environments.

2.缺点: 并不是一个高性能的引擎, 适用于单体应用.

3.说明: 如果要做一个高并发的应用, 选择前后端分离更好, 但是作为SpringBoot推荐的模板引擎, 我们还是要讲解Thymeleaf的使用, 这样大家在工作中如果使用到, 也能ok.

4.后面我们还要讲解 Vue + ElementPlus + Axios + SpringBoot 前后端分离.

Thymeleaf机制说明

1.Thymeleaf 是服务器渲染技术, 页面数据是在服务端进行渲染的.

2.比如: manage.html 中一段thymeleaf代码, 是在用户请求该页面时, 用thymeleaf模板引擎完成处理的(在服务端完成), 并将结果页面返回.

在这里插入图片描述

3.因此使用了Thymeleaf, 并不是前后端分离.

Thymeleaf语法

表达式

1.表达式一览

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

2.字面量
文本值: ‘zzw hello’, ‘hello’
数字: 10, 2.32, -2.33
布尔值: true, false
空值: null
变量: name, age(变量不能有空格)

3.文本操作
字符串拼接: +
变量替换: age = ${age}

运算符

1.数学运算
运算符: + - * / %

2.布尔运算
运算符: and, or
一元运算: ! not

3.比较运算
比较: > < >= <= (gt lt ge le)
等式: == != (eq ne)

4.条件运算
If-then:(if) ? (then)
If-then-else: (if) ? (then) : (else)
Default: (value) ?: (defaultvalue)

th属性

html有的属性, Thymeleaf基本都有, 而常用的属性大概有七八个, 其中th属性执行的优先级从1~8, 数字越低优先级越高

1.th:text: 设置当前元素的文本内容, 相同功能的还有th:utext, 两者的区别在于前者不会转义html标签, 后者会. 优先级不高: order=7
2.th:value: 设置当前元素的value值, 类似修改指定属性的还有th:src, th:href.优先级不高: order=6
3.th:each: 遍历循环元素, 和th:textth:value一起使用. 注意该属性修饰的标签位置, 优先级很高: order=2
4.th:if: 条件判断, 类似的还有th:unless, th:switch, th:case. 优先级较高: order=3
5.th:insert: 代码块引入, 类似的还有th:replace, th:include, 三者的区别较大, 或使用不恰当会破坏html结构, 常用于公共代码块提取的场景.优先级最高: order=1
6.th:fragment: 定义代码块, 方便被th:insert引用, 优先级最低: order=8
7.th:object: 声明变量, 一般和*{}一起配合使用, 达到偷懒的效果.优先级一般, order=4
8.th:attr: 修改任意属性, 实际开发中用的较少, 因为有丰富的其它th属性帮忙, 类似的还有th:attrappend, th:attrprepend. 优先级一般, order=5

迭代

如果没有走服务器渲染, 显示的是默认的值.

在这里插入图片描述

条件运算

th:href取得的值来替换href属性

在这里插入图片描述

使用Thymeleaf th属性需要注意点

1.若要使用Thymeleaf语法, 首先要声明名称空间: xmlns:th="http://www.thymeleaf.org"

2.设置文本内容th:text, 设置input的值th:value, 循环输出th:each, 条件判断th:if, 插入代码块th:insert, 定义代码块th:fragment, 声明变量th:object

3.th:each的用法需要格外注意, 打个比方: 如果你要循环一个div中的p标签, 则th:each属性必须放在p标签上. 若你将th:each属性放在div上, 则循环的将是整个div.

4.变量表达式中提供了很多的内置方法, 该内置方法使用#开头, 请不要与#{}消息表达式弄混.

Thymeleaf综合案例

需求说明

说明: 使用SpringBoot + Thymeleaf 完成简单的用户登录, 列表功能.

要求:
1.用户名未输入, 提示信息.
2.密码不是666, 提示不合法, 将错误信息回显
3.登陆成功在用户列表页面显示用户列表.

思路分析

说明: 使用SpringBoot + Thymeleaf完成简单的用户登录.

在这里插入图片描述

代码实现

1.创建项目, 项目名使用springboot-usersys, 这里使用灵活创建项目方式.

2.在pom.xml引入lombok, 并切换一下springboot版本

<!--导入springboot父工程-规定写法-->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.5.3</version>
</parent>

<dependencies>
    <!--导入web项目场景启动器, 会自动地导入和web开发相关的所有依赖[库/jar]-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!--引入lombok, 使用版本仲裁-->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>

3.引入spring-boot-configuration-processor, 在前面我们用过

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
</dependency>

4.引入thymeleaf-start: 项目会完成自动配置, 程序员按照规则开发即可

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

5.springboot系列三: sprintboot自动配置

在这里插入图片描述
在这里插入图片描述

6.类路径下引入static资源

7.创建templates/login.html(该目录不能直接访问)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>用户登录</title>
</head>
<body bgcolor="#CED3FE">
<img src="images/1.GIF">
<div style="text-align: center;">
    <h1>用户登陆</h1>
    <form action="#" method="post">
        <label style="color: red;"></label><br>
        用户名:<input type="text" style="width:150px" name="name"><br>
        密 码:<input type="password" style="width:150px" name="password"><br>
        <input type="submit" value="登录">
        <input type="reset" value="重新填写">
    </form>
</div>
</body>
</html>

8.创建src/main/java/com/zzw/springboot/controller/IndexController.java

@Controller
public class IndexController {
    //编写方法, 转发到 adminLogin.html(登陆页面)
    @GetMapping(value = {"/", "/login"})
    public String login() {
        /**
         * 解读
         * 1.这里我们引入了starter-thymeleaf
         * 2.这里就会直接使用视图解析到 thymeleaf 下的模板文件 adminLogin.html
         */
        return "adminLogin";
    }
}

9.启动, 浏览器请求 http://localhost:8080/

在这里插入图片描述

10.创建src/main/java/com/zzw/springboot/bean/Admin.java

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Admin {
    private String name;
    private String password;
}

11.创建src/main/java/com/zzw/springboot/bean/User.java

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private Integer id;
    private String name;
    private String password;
    private Integer age;
    private String email;
}

12.创建src/main/java/com/zzw/springboot/controller/AdminController.java
springboot支持复杂参数

@Controller
public class AdminController {
    //响应用户的登录请求
    @PostMapping("/login")
    public String login(Admin admin, HttpSession session, Model model) {

        //验证用户是否合法
        if (StringUtils.hasText(admin.getName()) && "666".equals(admin.getPassword())) {
            //合法, 携带user信息, 重定向到manage.html
            //回忆java web知识, 不使用请求转发, 防止刷新页面会重复提交
            //这里我们为什么是写的 manage.html, 因为这样可以更加明确地表示到哪个页面
            //manage.html 表示去找 方法的映射路径为 manage.html
            return "redirect:/manage.html";
        } else {
            //不合法, 返回登陆页面
            return "adminLogin";//走Thymeleaf的视图解析器
        }
    }

    //处理用户请求 manage.html
    @GetMapping("/manage.html")
    public String mainPage() {
        //用集合模拟用户数据, 放入到request域中, 并显示
        return "manage";//这里是我们的视图解析器,到 templates/manage.html
    }
}

13.创建 src/main/resources/templates/manage.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>管理后台</title>
</head>
<body bgcolor="#CED3FE">
<img src="images/1.GIF"/>
<a href='#'>返回管理界面</a>  <a href='#'>安全退出</a>   欢迎您:XXX
<hr/>
<div style="text-align: center">
    <h1>管理雇员~</h1>
    <table border="1px" cellspacing="0" bordercolor="green" style="width:800px;margin: auto">
        <tr bgcolor="pink">
            <td>id</td>
            <td>name</td>
            <td>pwd</td>
            <td>age</td>
            <td>email</td>
        </tr>
        <tr>
            <td>a</td>
            <td>b</td>
            <td>c</td>
            <td>d</td>
            <td>e</td>
        </tr>
    </table>
    <br/>
</div>
<hr/>
<img src="images/logo.png"/>
</body>
</html>

14.回填<form action=“login” method=“post”>, 相对路径是参考浏览器地址栏
不用回填, 因为action="#"就是action="/", 被解析成 http://localhost:8080/, 没有问题.

15.启动浏览器, http://localhost:8080/login, 用户名密码错误, 停留在登陆页面.

在这里插入图片描述

校验正确, 进入manage.html

在这里插入图片描述

16.补充AdminController.java

//处理用户请求 manage.html
@GetMapping("/manage.html")
public String mainPage(Model model) {
    //用集合模拟用户数据, 放入到request域中, 并显示
    List<User> users = new ArrayList<>();
    users.add(new User(1, "张三", "123456", 23, "张三@163.com"));
    users.add(new User(2, "李四", "123456", 24, "李四@163.com"));
    users.add(new User(3, "王五", "123456", 25, "王五@163.com"));
    users.add(new User(4, "赵六", "123456", 26, "赵六@163.com"));
    users.add(new User(5, "田七", "123456", 27, "田七@163.com"));

    //将数据放入到request域中
    model.addAttribute("users", users);

    return "manage";//这里是我们的视图解析器,到 templates/manage.html
}

17.补充manage.html, 显示用户列表

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>管理后台</title>
</head>
<body bgcolor="#CED3FE">
<img src="images/1.GIF"/>
<a href='#'>返回管理界面</a>  <a href='#'>安全退出</a>   欢迎您:XXX
<hr/>
<div style="text-align: center">
    <h1>管理雇员~</h1>
    <table border="1px" cellspacing="0" bordercolor="green" style="width:800px;margin: auto">
        <tr bgcolor="pink">
            <td>id</td>
            <td>name</td>
            <td>pwd</td>
            <td>age</td>
            <td>email</td>
        </tr>
        <tr bgcolor="#ffc0cb" th:each="user:${users}">
            <td th:text="${user.id}">a</td>
            <td th:text="${user.name}">b</td>
            <td th:text="${user.password}">c</td>
            <td th:text="${user.age}">d</td>
            <td th:text="${user.email}">e</td>
        </tr>
    </table>
    <br/>
</div>
<hr/>
<img src="images/logo.png"/>
</body>
</html>

18.测试

在这里插入图片描述

19.修改login.html
(1)显示登录错误信息

//不合法, 请求转发, 返回登陆页面
model.addAttribute("error", "用户名或密码错误");
return "adminLogin";//走Thymeleaf的视图解析器
<label style="color: red" th:text="${error}"></label><br/>
用户:<input type="text" style="width:150px" name="name"><br>

(2)修改提交的action

<form action="#" th:action="@{/login}" method="post">

(3)处理非法登录, 防止非法进入manage.html

@Controller
public class AdminController {
    //响应用户的登录请求
    @PostMapping("/login")
    public String login(Admin admin, HttpSession session, Model model) {

        //验证用户是否合法
        if (StringUtils.hasText(admin.getName()) && "666".equals(admin.getPassword())) {
            //将登陆用户保存到session
            session.setAttribute("loginAdmin", admin);

            //合法, 携带user信息, 重定向到manage.html
            //回忆java web知识, 不使用请求转发, 防止刷新页面会重复提交
            //这里我们为什么是写的 manage.html, 因为这样可以更加明确地表示到哪个页面
            //manage.html 表示去找 方法的映射路径为 manage.html
            return "redirect:/manage.html";
        } else {
            //不合法, 请求转发, 返回登陆页面
            model.addAttribute("error", "用户名或密码错误");
            return "adminLogin";//走Thymeleaf的视图解析器
        }
    }

    //处理用户请求 manage.html
    @GetMapping("/manage.html")
    public String mainPage(Model model,
                           @SessionAttribute(value = "loginAdmin", required = false) Admin admin) {
        //这里暂时在方法中验证, 后面我们统一使用拦截器
        if (admin == null) {
            model.addAttribute("error", "请先登录");
            return "adminLogin";//请求转发到 templates/adminLogin.html
        }
        //用集合模拟用户数据, 放入到request域中, 并显示
        List<User> users = new ArrayList<>();
        users.add(new User(1, "张三", "123456", 23, "张三@163.com"));
        users.add(new User(2, "李四", "123456", 24, "李四@163.com"));
        users.add(new User(3, "王五", "123456", 25, "王五@163.com"));
        users.add(new User(4, "赵六", "123456", 26, "赵六@163.com"));
        users.add(new User(5, "田七", "123456", 27, "田七@163.com"));

        //将数据放入到request域中
        model.addAttribute("users", users);
        return "manage";//这里是我们的视图解析器,到 templates/manage.html
    }
}

(4)登陆成功后信息显示, 行内写法

欢迎您:[[${session.loginAdmin.name}]]

5)安全退出

<a href='#' th:href="@{/}">安全退出</a>

作业布置

1.把前面我们学过的接收参数相关注解, 自定义转换器, 处理JSON, 内容协商, 相关代码和案例, 自己写一遍, 一定要自己写一遍, 否则没有印象, 理解不会深入.

2.将Thymeleaf用户管理 改成 妖怪管理列表, 字段做相应的改变, 进行联系.
1)Monster [id, name, skill, age, sal, birth]
2)基本界面保持不变
3)在完成过程中, 小伙伴会遇到各种问题, 要开始培养自己独立解决问题的能力了.

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

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

相关文章

自动导入unplugin-auto-import+unplugin-vue-components

文章介绍 接下来将会以Vite Vue3 TS的项目来举例实现 在我们进行项目开发时&#xff0c;无论是声明响应式数据使用的ref、reactive&#xff0c;或是各种生命周期&#xff0c;又或是computed、watch、watchEffect、provide-inject。这些都需要前置引入才能使用&#xff1a; …

Mem0:个性化的AI记忆层,一款开源的大语言记忆增强工具

在人工智能的浪潮中&#xff0c;个性化体验已成为创新的关键。而随着各种各样的模型迭代更新&#xff0c;如何为AI应用提供持久、智能的记忆系统逐渐成为了一个关键挑战。 最近开源的Mem0项目为我们提供了一个强大的解决方案。它为大型语言模型(LLM)提供了一个智能、自我优化的…

CTF ssrf 基础入门

0x01 引言 我发现我其实并不是很明白这个东西&#xff0c;有些微妙&#xff0c;而且记忆中也就记得Gopherus这个工具了&#xff0c;所以重新学习了一下&#xff0c;顺便记录一下吧 0x02 辨别 我们拿到一个题目&#xff0c;他的名字可能就是题目类型&#xff0c;但是也有可能…

昇思25天学习打卡营第九天|本地安装mindspore之一|Linux的系统在vmware上的安装以及mindspore的安装

课程已经学完了&#xff0c;打算再深入一些。初步的想法是&#xff0c;在本地安装&#xff0c;本地执行。 根据老师的指引&#xff0c;MindSpore官网&#xff0c;“https ://www.mindspore.cn/install/”&#xff0c;注意&#xff0c;因为csdn博客编辑器的原因&#xff0c;当我…

C#与C++交互开发系列(三):深入探讨P/Invoke基础知识

欢迎来到C#与C交互开发系列的第三篇。在这篇博客中&#xff0c;我们将深入探讨P/Invoke&#xff08;Platform Invocation Services&#xff09;的基础知识。P/Invoke是C#调用非托管代码的一种机制&#xff0c;能够让C#直接调用C编写的动态链接库&#xff08;DLL&#xff09;中的…

轻松翻译,你值得拥有的PDF翻译工具分享

大家好&#xff0c;作为一名初入职场的小菜鸟&#xff0c;我发现了一个让我头疼不已的问题——那就是PDF文件的翻译。在全球化日益加剧的今天&#xff0c;我们经常会遇到需要阅读或者翻译外文PDF文件的情况。但PDF文件不同于Word或Excel&#xff0c;它通常不易直接编辑&#xf…

C语言 | Leetcode C语言题解之第278题第一个错误的版本

题目&#xff1a; 题解&#xff1a; int firstBadVersion(int n) {int left 1, right n;while (left < right) { // 循环直至区间左右端点相同int mid left (right - left) / 2; // 防止计算时溢出if (isBadVersion(mid)) {right mid; // 答案在区间 [left, mid] 中…

SWAT模型

原文链接&#xff1a;SWAT模型https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247610033&idx2&snc1da9be73550928ecc6a7a165dda3d9c&chksmfa826f56cdf5e640f891c6977cec1b2728ee2554ceacd224903df73d2dfedcd0c8b9ec047843&token91118244&langzh…

uniapp入门超详细教程:如何从零开始搭建项目

目录 一、介绍 二、环境搭建 2.1.需要下载的软件 2.1.1 HBuilderX 2.1.2 下载微信开发者工具 2.2 创建uniapp项目 2.2.1 新建项目 2.2.2 项目基本结构 2.2.3 在微信开发者工具上运行 2.2.4 发布微信小程序 三、pages.json 页面路由 四、组件 4.1 视图容器 4.1.1 v…

超分AI模型学习

概述 超分&#xff08;超分辨率&#xff1a;Super Resolution&#xff0c;SR&#xff09;&#xff1a;是计算机视觉和图像处理领域的一个热门话题。主要是将低分辨率图像恢复出高分辨率图像。可以采用的方法和手段很多&#xff0c;最近项目中有涉及&#xff08;红外成像的超分处…

Axivion Suite 7.8现已发布

现已实现100%覆盖MISRA规则&#xff0c;并加入了高级功能来提高代码分析能力。 我们很高兴地宣布Axivion Suite 7.8发布。全新版本的Axivion Suite对编译器、配置、分析、仪表板 (WebUI)和IDE插件的架构验证和静态代码分析功能均进行了升级。 100%覆盖所有可测试的MISRA规则 …

centos系统mysql集群复制双主双从

文章目录 MySQL 双主双从集群一、 准备环境二、 配置主服务器1. 配置 MySQL 主服务器 1 (192.168.1.1)2. 配置 MySQL 主服务器 2 (192.168.1.2) 三、配置从服务器1. 配置 MySQL 从服务器 1 (192.168.1.3)2. 配置 MySQL 从服务器 2 (192.168.1.4)3. 在主服务器 1 上配置复制到主…

使用php adodb5连接人大金仓数据库

打开php中的pgsql扩展 extensionpgsql使用adodb5连接kingbase数据库 <?php include("adodb5/adodb.inc.php"); $fox_dbtype pgsql; $fox_host 192.168.1.66; $fox_user system; $fox_pwd 123456; $fox_dbname testkingbase; $fox_port 54321;$dbNewADOCo…

【实战】Spring Cloud Stream3.0 整合RocketMq

文章目录 前言技术积累Spring Cloud Stream3.0新特性RocketMq简介 实战演示引入Maven依赖增加application配置消息生产者消息消费者 前言 相信很多同学用使用过rocketmq消息中间件&#xff0c;且大多情况下是使用原生的rocketmq-spring-boot-starter 进行集成然后创建一个rock…

Unity显示泰语且兼容泰语音标

前言&#xff1a;使用Unity开发的游戏需要支持泰语本地化&#xff0c;以及解决显示泰语时Unity的bug 目录 1、Text组件显示泰语2、TextMeshPro组件显示泰语 现在很多游戏都需要显示泰语&#xff0c;下面将介绍Unity如何显示泰语&#xff0c;&#xff08;仅介绍Unity字体方面的设…

Transformer自然语言处理实战pdf阅读

一.第一章 欢迎来到transformer的世界 1.解码器-编码器框架 在Transformer出现之前&#xff0c;NLP的最新技术是LSTM等循环架构。这些架 构通过在神经网络连接使用反馈循环&#xff0c;允许信息从一步传播到另一 步&#xff0c;使其成为对文本等序列数据进行建模的理想选择。如…

多表查询时条件写在where和join on的区别

文章目录 一、初始数据二、问题分析三、总结 先说结论&#xff0c; 1.如果想要拿到主表不受到关联表查询条件的数据的话&#xff0c;那么建议直接将查询条件放到on之后。 2.如果将关联表的条件查询放在where之后&#xff0c;可能会将主表中的数据进行排除。 所以如果想实现的查…

总结一些vue3小知识3

1.限制时间选择器只能选择后面的日期 说明&#xff1a;disabled-date属性是一个用来判断该日期是否被禁用的函数&#xff0c;接受一个 Date 对象作为参数。 应该返回一个 Boolean 值。 <el-date-picker class"w180" v-model"datas.form.timeDate[0]" …

6.6 使用dashboard商城搜索导入模板

本节重点介绍 : 模板商城中搜索模板导入模板修改模板 大盘模板商城地址 免费的 地址 https://grafana.com/grafana/dashboards 搜索模板技巧 详情 导入dashboard 两种导入模式 url导入id导入json文件导入 导入 node_exporter模板 https://grafana.com/grafana/dashboa…

萤石举办2024夏季新品发布会,全力推进“2+5+N”智能家居新生态

7月24日&#xff0c;“智动新生&#xff0c;尽在掌控”2024萤石夏季新品发布会在杭州成功举办。本次发布会上&#xff0c;“智慧生活守护者”萤石深入挖掘应用场景&#xff0c;重磅发布了包括智能健康手表、智能家居AI主机、生态控制器、智家APP等多款创新性的产品及应用&#…