Thymeleaf实战:SpringBoot用户管理系统

 Thymeleaf 示例代码

下面是完整代码示例,帮助理解 Thymeleaf 语法和后端代码的配合:

1. 用户实体类 (User.java)

/*** 用户实体类*/
public class User {private Long id;          // 用户IDprivate String name;     // 用户名private String email;    // 邮箱private boolean admin;   // 是否是管理员private LocalDate birthDate; // 生日private double balance;  // 账户余额// 构造方法public User(Long id, String name, String email, boolean admin, LocalDate birthDate, double balance) {this.id = id;this.name = name;this.email = email;this.admin = admin;this.birthDate = birthDate;this.balance = balance;}// Getter和Setter方法public Long getId() {return id;}public void setId(Long id) {this.id = id;}// ... 其他getter/setter方法省略
}

2. 控制器 (UserController.java)

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;import java.time.LocalDate;
import java.util.Arrays;
import java.util.List;@Controller
@RequestMapping("/users")
public class UserController {// 模拟数据库中的用户数据private List<User> users = Arrays.asList(new User(1L, "张三", "zhangsan@example.com", false, LocalDate.of(1990, 5, 15), 1500.50),new User(2L, "李四", "lisi@example.com", true, LocalDate.of(1985, 8,  ㅇ20), 2500.75),new User(3L, "王五", "wangwu@example.com", false, LocalDate.of(1995, 3, 10), 1800.00));/*** 显示用户列表页面* @param model 用于向视图传递数据的模型对象* @return 视图名称*/@GetMappingpublic String listUsers(Model model) {// 将用户列表添加到模型中,供Thymeleaf使用model.addAttribute("users", users);// 添加当前日期到模型中model.addAttribute("currentDate", LocalDate.now());// 返回视图名称(对应src/main/resources/templates/user/list.html)return "user/list";}/*** 显示用户详情页面* @param id 用户ID* @param model 模型对象* @return 视图名称*/@GetMapping("/{id}")public String userDetail(@PathVariable Long id, Model model) {// 根据ID查找用户User user = users.stream().filter(u -> u.getId().equals(id)).findFirst().orElse(null);// 将用户对象添加到模型中model.addAttribute("user", user);// 返回用户详情视图return "user/detail";}/*** 显示编辑用户表单* @param id 用户ID* @param model 模型对象* @return 视图名称*/@GetMapping("/{id}/edit")public String editUserForm(@PathVariable Long id, Model model) {// 根据ID查找用户User user = users.stream().filter(u -> u.getId().equals(id)).findFirst().orElse(null);// 将用户对象添加到模型中model.addAttribute("user", user);// 返回编辑表单视图return "user/edit";}/*** 处理编辑表单提交* @param id 用户ID* @param user 表单绑定的用户对象* @return 重定向到用户详情页面*/@PostMapping("/{id}/edit")public String submitEdit(@PathVariable Long id, @ModelAttribute User user) {// 在实际应用中,这里应该更新数据库System.out.println("更新用户: " + user);// 重定向到用户详情页面return "redirect:/users/" + id;}
}

3. Thymeleaf 模板示例

用户列表页面 (list.html)

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"> <!-- 声明Thymeleaf命名空间 -->
<head><meta charset="UTF-8"><title>用户列表</title><!-- 引入Bootstrap CSS --><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css">
</head>
<body><div class="container mt-5"><!-- 页面标题 --><h1>用户列表</h1><!-- 显示当前日期 --><p>当前日期: <span th:text="${#dates.format(currentDate, 'yyyy年MM月dd日')}"><!-- 静态默认值,当Thymeleaf未处理时显示 -->2023-01-01</span></p><!-- 条件判断:如果没有用户数据 --><div th:if="${#lists.isEmpty(users)}" class="alert alert-warning">没有找到用户数据</div><!-- 条件判断:如果有用户数据 --><table class="table table-striped" th:unless="${#lists.isEmpty(users)}"><thead><tr><th>ID</th><th>姓名</th><th>邮箱</th><th>管理员</th><th>余额</th><th>操作</th></tr></thead><tbody><!-- 循环遍历用户列表 --><!-- th:each="user, stat : ${users}" user: 当前迭代的用户对象stat: 迭代状态对象,包含index, count, size等信息--><tr th:each="user, stat : ${users}"><td th:text="${user.id}">1</td><td><!-- 链接表达式:生成动态URL --><a th:href="@{/users/{id}(id=${user.id})}" th:text="${user.name}">姓名</a></td><td th:text="${user.email}">邮箱</td><td><!-- 条件判断:如果是管理员 --><span th:if="${user.admin}" class="badge bg-success">是</span><!-- 条件判断:如果不是管理员 --><span th:unless="${user.admin}" class="badge bg-secondary">否</span></td><td><!-- 数字格式化:将余额格式化为货币形式 --><span th:text="${#numbers.formatCurrency(user.balance)}">$0.00</span></td><td><!-- 编辑按钮 --><a th:href="@{/users/{id}/edit(id=${user.id})}" class="btn btn-sm btn-primary">编辑</a></td></tr></tbody></table></div>
</body>
</html>

用户详情页面 (detail.html)

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>用户详情</title><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css">
</head>
<body><div class="container mt-5"><h1>用户详情</h1><!-- 使用选择表达式:设置上下文对象为user --><div th:object="${user}"><!-- th:object="${user}" 设置当前上下文对象在div内部可以使用 *{...} 代替 ${user...}--><p>ID: <span th:text="*{id}">1</span></p><p>姓名: <span th:text="*{name}">姓名</span></p><p>邮箱: <span th:text="*{email}">邮箱</span></p><p>管理员: <!-- 三元表达式:根据admin值显示"是"或"否" --><span th:text="*{admin} ? '是' : '否'">是/否</span></p><p>生日: <!-- 日期格式化:将日期格式化为指定格式 --><span th:text="${#dates.format(user.birthDate, 'yyyy年MM月dd日')}">1990-01-01</span></p><p>余额: <!-- 数字格式化:将余额格式化为货币形式 --><span th:text="${#numbers.formatCurrency(user.balance)}">$0.00</span></p></div><!-- 返回用户列表的链接 --><a th:href="@{/users}" class="btn btn-secondary">返回列表</a></div>
</body>
</html>

编辑用户页面 (edit.html)

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>编辑用户</title><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css">
</head>
<body><div class="container mt-5"><h1>编辑用户</h1><!-- 表单绑定:th:action="@{/users/{id}/edit(id=${user.id})}" - 表单提交地址th:object="${user}" - 绑定表单数据到user对象method="post" - 提交方法--><form th:action="@{/users/{id}/edit(id=${user.id})}" th:object="${user}" method="post"><!-- ID字段(只读) --><div class="mb-3"><label class="form-label">ID</label><!-- th:field="*{id}" 绑定到user对象的id属性 --><input type="text" class="form-control" th:field="*{id}" readonly></div><!-- 姓名字段 --><div class="mb-3"><label class="form-label">姓名</label><!-- th:field="*{name}" 绑定到user对象的name属性 --><input type="text" class="form-control" th:field="*{name}"></div><!-- 邮箱字段 --><div class="mb-3"><label class="form-label">邮箱</label><input type="email" class="form-control" th:field="*{email}"></div><!-- 管理员复选框 --><div class="mb-3 form-check"><!-- th:field="*{admin}" 绑定到user对象的admin属性 --><input type="checkbox" class="form-check-input" th:field="*{admin}"><label class="form-check-label">管理员</label></div><!-- 生日字段 --><div class="mb-3"><label class="form-label">生日</label><input type="date" class="form-control" th:field="*{birthDate}"></div><!-- 余额字段 --><div class="mb-3"><label class="form-label">余额</label><input type="number" step="0.01" class="form-control" th:field="*{balance}"></div><!-- 提交按钮 --><button type="submit" class="btn btn-primary">保存</button><!-- 取消按钮(返回用户详情) --><a th:href="@{/users/{id}(id=${user.id})}" class="btn btn-secondary">取消</a></form></div>
</body>
</html>

4. 关键注释总结

1. 后端控制器注释

  • ​@Controller​:标记类为Spring MVC控制器
  • ​@RequestMapping​:映射控制器处理的URL路径
  • ​@GetMapping/@PostMapping​:映射HTTP GET/POST请求
  • ​@PathVariable​:获取URL路径中的变量
  • ​@ModelAttribute​:将表单数据绑定到对象
  • Model​:用于在控制器和视图之间传递数据

2. Thymeleaf 语法注释

  • th:text​:设置元素的文本内容
  • th:if/th:unless​:条件渲染
  • th:each​:循环迭代
  • th:object​:设置上下文对象
  • th:field​:表单字段绑定
  • th:href​:动态生成链接
  • ​${...}​​:变量表达式
  • ​*{...}​​:选择表达式(在th:object内部使用)
  • ​@{...}​​:链接表达式
  • ​#dates​:日期处理工具
  • ​#numbers​:数字处理工具
  • ​#lists​:集合处理工具

3. 前端模板注释

  • 静态默认值​:在Thymeleaf处理前显示的内容
  • Bootstrap类​:用于页面样式
  • 表单绑定​:th:object和th:field配合实现数据绑定
  • 表达式注释​:解释各种Thymeleaf表达式的用途

这些注释详细解释了代码的每个部分如何工作,以及Thymeleaf语法如何与后端Spring Boot控制器配合使用。通过阅读这些注释,可以更好地理解Thymeleaf的核心概念和工作原理。

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

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

相关文章

mysql查找数据库表中某几个连续的编号中中断的编号

在MySQL中查找表中连续编号中断的位置,可以通过以下几种方法实现: 基于范围的查询方法 通过自连接查询找出ID序列中的断点,例如查找1-100范围内缺失的ID: SELECT a.id + 1 AS start, MIN(b.id) - 1 AS end FROM

《剑指offer》-数据结构篇-树

题目重建二叉树树的子结构二叉树的镜像从上往下打印二叉树&#xff08;层序遍历&#xff09;把二叉树打印成多行按之字形顺序打印二叉树二叉搜索树的第k个结点&#xff08;中序遍历&#xff09;二叉搜索树的后序遍历序列&#xff08;后序遍历&#xff09;二叉树中和为某一值的路…

系统定时任务扩展开发指南

适用场景当系统内置定时任务类型无法满足业务需求时&#xff0c;开发者可通过本教程快速掌握自定义定时任务的扩展方法。本指南以"定时检测服务"为例&#xff0c;演示完整开发流程。我想添加一个定时任务 ,而这里没有我需要的,我怎么来添加比如我想添加一个定时检测用…

R语言简介(附电子书资料)

概述 R语言是一种专为统计计算和数据分析设计的编程语言&#xff0c;自诞生以来&#xff0c;凭借其强大的统计分析能力和丰富的可视化功能&#xff0c;成为数据科学、统计学、机器学习等领域的重要工具。电子书资料&#xff1a;https://pan.quark.cn/s/23050825f2be 一、核心特…

关于前端的性能优化

性能优化主要涵盖了以下四个方面: (tip:仅代表个人总结,如有不当,还希望看到的大佬多多指示) 减少网络请求:合并文件、使用 CDN、启用缓存。 优化资源加载:代码分割、懒加载、图片压缩。 提升渲染性能:减少重绘回流、防抖节流、使用 Web Worker。 监控和迭代:定期使用工…

用 FFmpeg 把视频输出为图片序列

用 FFmpeg 把视频输出为图片序列 【推荐】输出为PNG图片序列&#xff08;无损&#xff09; mkdir "D:\Downloads\Recording" ffmpeg -i "C:\Users\33589\Videos\1.mp4" "D:\Downloads\Recording\Recording_%05d.png" 参数含义-i输入视频路径&am…

【linux】高可用集群Keepalived

Keepalived简介Keepalived 是一个基于 VRRP&#xff08;虚拟路由冗余协议&#xff09;的高可用解决方案&#xff0c;主要用于实现 Linux 服务器的负载均衡和故障转移。它通过检测服务器状态并自动切换服务&#xff0c;确保系统在单点故障时仍能保持可用性Keeplived安装启用及配…

如何检查服务器数据盘是否挂载成功?

在服务器配置过程中&#xff0c;确保数据盘正确挂载是非常重要的。如果数据盘未挂载成功&#xff0c;您可能无法访问数据盘上的存储空间。以下是检查Linux服务器中数据盘是否挂载成功的详细步骤&#xff0c;以及如何解决挂载问题。1. 检查数据盘是否挂载成功1.1 使用 df -h 查看…

机器学习概述与 KNN 算法详解

机器学习概述与 KNN 算法详解引言在当今数字化时代&#xff0c;机器学习作为人工智能的核心技术&#xff0c;正深刻改变着我们的生活与工作方式。从日常的智能推荐到复杂的医疗诊断&#xff0c;机器学习技术的应用无处不在。本文将从机器学习的基本概念出发&#xff0c;阐述其核…

Java EE前端技术编程脚本语言JavaScript

-CoderOilStation(程序员编程助手科技股份责任有限公司)Java EE前端技术编程脚本语言JavaScript低代码编程技术编写少量的代码规则。JavaScript脚本编程语言具体细节配置方式编程。前端技术过渡web3.0企业数字化。Java Service Page (JSP) JavaEE jdk6.5 发布企业应用版本Java研…

Docker+Kubernetes 实战:数据模型的弹性伸缩与高可用部署方案

在生产环境中,数据模型的部署面临双重挑战:一方面要应对流量波动(如电商大促期间预测接口调用量激增 10 倍),另一方面需保证服务零中断(金融风控模型 downtime 每增加 1 分钟可能导致数十万元损失)。 本文基于实际项目经验,详细讲解如何通过 Docker 容器化与 Kubernet…

vue3【组件封装】头像裁剪 S-avatar.vue

最终效果 技术要点 图片裁剪 安装依赖 vue-cropper npm install vue-croppernext专用于vue3 项目的图片裁剪&#xff0c;详细使用参考官方文档 页面使用 import "vue-cropper/dist/index.css"; import { VueCropper } from "vue-cropper";<vue-crop…

铜金矿数据分组优化系统设计与实现

铜金矿数据分组优化系统设计与实现 1. 项目概述 本项目旨在开发一个Python程序,用于根据给定的四组分组规则,优化包含金吨、干吨和铜单价等信息的Excel数据分组,以最大化总金额。系统需要处理的核心计算是每条数据的铜货值,其公式为:结算铜金吨 铜单价 (价格系数 + 奖…

Python动态规划:从基础到高阶优化的全面指南(3)

七、动态规划性能优化实战7.1 矩阵快速幂优化def matrix_mult(A, B):"""矩阵乘法"""n len(A)m len(B[0])p len(B)C [[0]*m for _ in range(n)]for i in range(n):for k in range(p):if A[i][k]:for j in range(m):C[i][j] A[i][k] * B[k][j…

海外红人营销的下一站:APP出海如何布局虚拟网红与UGC生态?

在全球移动互联网竞争日益激烈的今天&#xff0c;APP出海推广的重心正从传统流量采买和真人KOL合作&#xff0c;逐步向更具未来感的方向演进。虚拟网红、AI生成内容以及用户生成内容的融合&#xff0c;正为海外红人营销注入全新活力。这不仅是技术革新&#xff0c;更是用户行为…

CentOS网卡未被托管解决记录

VMWare挂起关机&#xff0c;又重启后&#xff0c;出现一些很奇怪的问题。 我的几台CentOS的网卡都不见了&#xff0c;显示网卡未被托管 [rootlocalhost ~]# nmcli device status DEVICE TYPE STATE CONNECTION virbr0 bridge 未托管 -- ens33 …

Node.js 中的内置模板path

1. path的作用&#xff1a;path 是 Node.js 中的一个内置模块&#xff0c;用于处理文件和目录路径。它提供了一些工具来处理路径字符串&#xff0c;确保路径操作跨平台兼容&#xff08;Windows 和 Unix 风格的路径分隔符&#xff09;2.path的常用方法path.join()和数组的join方…

重生之我在暑假学习微服务第三天《Docker-上篇》

个人主页&#xff1a;VON文章所属专栏&#xff1a;微服务系列文章链接&#xff1a;重生之我在暑假学习微服务第一天《MybatisPlus-上篇》-CSDN博客重生之我在暑假学习微服务第二天《MybatisPlus-下篇》-CSDN博客时间&#xff1a;每天12点前准时更新 特别声明&#xff1a;本篇文…

【硬件】LT3763中文手册

目录 1.简介 1.1 特点 1.2 简述 1.3 典型原理图 1.4 绝对最大额定值 2.电气特性 3.引脚功能 4.框图 4.1 设计电感电流 4.2 电感选择 4.3 开关MOSFET选择 4.4 输入电容选择 4.5 输出电容选择 4.6 CBOOST电容选择 4.7 INTVCC电容器选择 4.8 Soft-Start 4.9 输出电流…

【计算机科学与应用】基于多域变换的视频水印嵌入算法研究

导读&#xff1a; 为提升视频水印在版权保护中的实际应用效果&#xff0c;本文提出一种基于多域变换的视频水印嵌入算法。该算法结合离散小波变换(Discrete Wavelet Transform, DWT)与离散余弦变换(Discrete Cosine Transformation, DCT)&#xff0c;利用其在时频域分析与能量…