第六章 Web开发:Thymeleaf模板引擎
学习目标
如果没有了解可以去我主页看看 第一至五章的内容来学习)上一章我们对一些表示层相关的技术点进行了学习,基于MyBAtis-Plus和JSP实现了简单的用户操作。其实Spring Boot是不推荐使用JSP作为视图的,默认使用Thymeleaf模板。
本章我们将学习到Thymeleaf模板的一些相关概念,核心语法,还将学习页面布局,最后使用本次学习到的知识点,结合JPA,完成用户的登录、列表及客户关系管理系统后台主页面的布局。
6.1 Thymeleaf简介
6.1.1 模板引擎
模板引擎是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档。
模板引擎的实现方式有很多,最简单的是"置换型"模板引擎,这类模板引擎只是将指定模板内容(字符串)中的特定标记(子字符串)替换,便生成了最终需要的业务数据(如网页)。
"置换型"模板引擎实现简单,但其效率低下,无法满足高负载的应用需求(比如有海量访问的网站),因此还出现了"解释型"模板引擎和"编译型"模板引擎等。
6.1.2 Thymeleaf介绍
Thymeleaf 是一个用于处理HTML, XML, JavaScript, CSS 和纯文本文件的现代服务器端Java模板引擎。它非常适合于Web和独立环境中的应用程序。在Java项目中,特别是与Spring框架结合使用时,Thymeleaf提供了一种非常优雅的方式来渲染动态内容到Web页面上。
下面是一个简单的Java代码示例,展示了如何在Spring Boot项目中与Thymeleaf一起工作。请注意,这个示例假设你已经有一个Spring Boot项目,并且已经添加了spring-boot-starter-thymeleaf依赖到你的pom.xml(Maven)或build.gradle(Gradle)文件中。
1. 控制器(Controller)
首先,你需要一个控制器来处理Web请求并返回Thymeleaf模板。
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HelloController {
@GetMapping("/")
public String hello(Model model) {
// 添加一些数据到模型中
model.addAttribute("message", "Hello, Thymeleaf!");
// 返回模板的名称,Spring Boot会在/templates目录下查找对应的HTML文件
return "hello";
}
}
2. Thymeleaf模板(HTML)
然后,在src/main/resources/templates目录下创建一个名为hello.html的Thymeleaf模板文件。这个文件将使用Thymeleaf的语法来显示动态内容。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Hello Thymeleaf</title>
</head>
<body>
<h1 th:text="${message}">Hello, World!</h1>
</body>
</html>
在这个模板中,th:text="${message}“是Thymeleaf的语法,它告诉Thymeleaf将model中名为message的属性的值插入到<h1>
标签的文本内容中。如果model中没有message属性,或者其值为null,则<h1>
标签的文本内容将是其默认的"Hello, World!”。
3. 运行和测试
现在,当你运行Spring Boot应用程序并访问根URL(通常是http://localhost:8080/)时,你应该会看到一个包含"Hello, Thymeleaf!"文本的网页。
6.1.3 Thymeleaf特点
Thymeleaf 作为一个现代服务器端Java模板引擎,具有许多特点,这些特点使得它成为Java Web开发中一个受欢迎的选择,尤其是在与Spring框架结合使用时。以下是Thymeleaf的一些主要特点,并通过简短的Java代码示例来展示这些特点如何在实践中应用(尽管代码示例本身可能无法直接展示所有特点,但会尽量体现其核心理念)。
1. 自然模板(Natural Templates)
Thymeleaf 允许开发者编写标准的HTML/XML模板,然后在需要的地方添加Thymeleaf特定的属性来实现动态内容。这意味着前端开发者可以更容易地理解和维护模板。
Java 代码示例(这里主要是控制器逻辑,但体现了自然模板的概念):
@Controller
public class NaturalTemplateController {
@GetMapping("/natural")
public String naturalTemplate(Model model) {
model.addAttribute("title", "自然模板示例");
model.addAttribute("greeting", "欢迎使用Thymeleaf的自然模板特性!");
return "naturalTemplate"; // 返回的是HTML文件名,Thymeleaf会处理它
}
}
在naturalTemplate.html中,你可以这样使用Thymeleaf语法:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title th:text="${title}">页面标题</title>
</head>
<body>
<h1 th:text="${greeting}">默认问候语</h1>
</body>
</html>
2. 丰富的表达式语言
Thymeleaf 提供了强大的表达式语言,允许开发者在模板中执行复杂的逻辑操作。
Java 代码示例(控制器逻辑通常不涉及表达式语言的直接应用,但可以在模型中准备数据):
// 假设这是控制器的一部分,准备了一些数据
model.addAttribute("users", Arrays.asList(
new User("Alice", 30),
new User("Bob", 25)
));
在模板中,你可以使用Thymeleaf的表达式语言来遍历这个列表:
<ul>
<li th:each="user : ${users}" th:text="${user.name} + ' (' + ${user.age} + '岁)'"></li>
</ul>
3. 与Spring的无缝集成
Thymeleaf 与 Spring 框架(特别是Spring MVC)无缝集成,使得在Spring应用程序中使用Thymeleaf变得非常简单。
特点体现:上面给出的所有Java代码示例都是基于Spring MVC控制器的,这展示了Thymeleaf与Spring的紧密集成。
4. 安全性
Thymeleaf 的设计考虑了安全性,特别是防止跨站脚本(XSS)攻击。它允许开发者通过特定的属性(如th:utext)来明确指定哪些内容是安全的,应该被作为HTML处理,哪些内容应该被转义以防止XSS攻击。
Java 代码示例(这里主要体现的是模板层面的安全性意识,而不是Java代码):
在模板中,使用th:text而不是th:utext来确保内容被正确转义:
<p th:text="${unsafeContent}">这里的内容会被转义</p>
<!-- 如果确实需要渲染HTML,且确定内容是安全的,可以使用th:utext -->
<p th:utext="${safeHtmlContent}">这里的内容会被作为HTML解析</p>
5. 性能
Thymeleaf 的性能表现良好,特别是在处理大型模板和复杂的数据模型时。它支持缓存和预编译,以减少渲染时间。
注意:性能特点通常不是通过单个Java代码示例来直接展示的,而是通过整体架构设计、缓存策略以及Thymeleaf配置来体现的。
6.2 快速上手
要快速上手使用JPA(Java Persistence API)和Thymeleaf在Java Web项目中,我们通常会结合Spring Boot框架,因为它大大简化了配置和依赖管理。以下是一个简单的步骤和代码示例,帮助你开始使用JPA进行数据持久化和Thymeleaf进行视图渲染。
1. 创建Spring Boot项目
首先,你可以使用Spring Initializr 来快速生成一个Spring Boot项目。在生成项目时,选择以下依赖:
- Spring Web
- Spring Data JPA
- Thymeleaf
- H2 Database(或其他数据库,如MySQL、PostgreSQL等)
2. 配置数据库
在src/main/resources/application.properties或application.yml文件中配置数据库连接。以下是一个使用H2数据库的示例:
# application.properties
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.h2.console.enabled=true
3. 创建实体类
在src/main/java/com/yourcompany/yourapp/model(或你选择的包路径)下创建一个实体类。例如,一个Person类:
package com.yourcompany.yourapp.model;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private int age;
// 构造函数、getter和setter省略
}
4. 创建仓库接口
在src/main/java/com/yourcompany/yourapp/repository下创建一个继承自JpaRepository的接口。例如,一个PersonRepository:
package com.yourcompany.yourapp.repository;
import com.yourcompany.yourapp.model.Person;
import org.springframework.data.jpa.repository.JpaRepository;
public interface PersonRepository extends JpaRepository<Person, Long> {
// 这里可以定义额外的查询方法,但JpaRepository已经提供了很多基本方法
}
5. 创建控制器
在src/main/java/com/yourcompany/yourapp/controller下创建一个控制器类。例如,一个PersonController:
package com.yourcompany.yourapp.controller;
import com.yourcompany.yourapp.model.Person;
import com.yourcompany.yourapp.repository.PersonRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class PersonController {
@Autowired
private PersonRepository personRepository;
@GetMapping("/")
public String listPersons(Model model) {
model.addAttribute("persons", personRepository.findAll());
return "persons"; // 返回Thymeleaf模板的名称
}
}
6. 创建Thymeleaf模板
在src/main/resources/templates目录下创建一个名为persons.html的Thymeleaf模板文件:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Persons</title>
</head>
<body>
<h1>Persons</h1>
<ul>
<li th:each="person : ${persons}" th:text="${person.name} + ' (' + ${person.age} + ' years old)'"></li>
</ul>
</body>
</html>
7. 运行和测试
现在,你可以运行你的Spring Boot应用程序,并访问http://localhost:8080/(或你配置的任何其他端口)来查看结果。你应该会看到一个列出所有Person对象的页面。
以上步骤和代码示例提供了一个简单的起点,帮助你开始使用JPA进行数据持久化和Thymeleaf进行视图渲染。你可以根据需要扩展和修改这些代码。
6.3 核心语法
我们接下来学习Thymeleaf的核心语法!!!
6.3.1 Thymeleaf配置
在Spring Boot项目中,Thymeleaf的配置通常是通过application.properties或application.yml文件来进行的,因为Spring Boot提供了自动配置功能,可以自动检测并配置Thymeleaf。然而,有时候你可能需要更细粒度的控制,这时你可以通过Java代码来配置Thymeleaf。
要通过Java代码配置Thymeleaf,你需要创建一个配置类,并使用@Configuration注解标记它。然后,你可以使用@Bean注解来定义Thymeleaf相关的bean,这些bean将覆盖或补充Spring Boot的自动配置。
以下是一个简单的示例,展示了如何通过Java代码来配置Thymeleaf的一些基本属性:
package com.yourcompany.yourapp.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.spring5.SpringTemplateEngine;
import org.thymeleaf.spring5.templateresolver.SpringResourceTemplateResolver;
import org.thymeleaf.templatemode.TemplateMode;
@Configuration
public class ThymeleafConfig {
@Bean
public SpringResourceTemplateResolver templateResolver() {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setPrefix("/templates/");
resolver.setSuffix(".html");
resolver.setTemplateMode(TemplateMode.HTML);
resolver.setCharacterEncoding("UTF-8");
resolver.setCacheable(false); // 开发时设置为false,以便及时看到模板更改
return resolver;
}
@Bean
public TemplateEngine templateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver(templateResolver());
// 这里可以添加更多的配置,比如消息解析器、方言等
return engine;
}
// 注意:在Spring Boot中,如果你只是想要修改默认配置(如模板位置、后缀等),
// 通常不需要显式地创建TemplateEngine bean,因为Spring Boot会自动配置它。
// 但如果你需要完全控制Thymeleaf的行为,或者你想要集成自定义的模板解析器等,
// 那么就需要像上面那样显式地定义bean。
}
然而,需要注意的是,在大多数Spring Boot项目中,你实际上可能不需要上面的配置,因为Spring Boot已经为你配置好了Thymeleaf。上面的配置主要是为了展示如何通过Java代码来定制Thymeleaf的行为。
如果你只是想要修改一些默认的配置(比如模板的位置、后缀等),你通常可以直接在application.properties或application.yml文件中进行设置,如下所示:
# application.properties
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html
spring.thymeleaf.mode=HTML
spring.thymeleaf.encoding=UTF-8
spring.thymeleaf.cache=false # 开发时设置为false
或者,如果你使用的是YAML格式的配置文件:
# application.yml
spring:
thymeleaf:
prefix: classpath:/templates/
suffix: .html
mode: HTML
encoding: UTF-8
cache: false # 开发时设置为false
总之,虽然你可以通过Java代码来配置Thymeleaf,但在Spring Boot项目中,通常推荐使用application.properties或application.yml文件来进行配置,因为这样做更简单、更直观。
6.3.2 表达式
Thymeleaf要输出数据,一般是通过表达式和标签配合实现(类似EL+JSTL),我们先来学习一下Thymeleaf的表达式。
Thymeleaf表达式共分为以下五类:
- 变量表达式:${…}
- 选择或星号表达式:*{…}
- 文字国际化表达式:#{…}
- URL表达式:@{…}
- 片段表达式:~{…}
本次我们重点学习变量表达式、选择表达式和URL表达式,片段表达式放在第四小节再讲解。
6.3.2.1变量表达式
在Thymeleaf中,变量表达式用于在模板中访问模型(Model)数据。这些数据通常是在控制器(Controller)中准备好的,并通过模型(Model)或模型映射(ModelMap)传递给视图(View)的。在Thymeleaf模板中,你可以使用${…}语法来访问这些变量。
然而,你提到的“Java代码”可能意味着你想了解如何在后端Java代码中设置这些变量,或者在Thymeleaf模板中如何使用Java代码片段(虽然Thymeleaf本身不直接支持在模板中嵌入Java代码)。
在Java代码中设置变量
在Spring MVC或Spring Boot中,你通常会在控制器(Controller)的方法中设置模型数据。例如:
@Controller
public class MyController {
@GetMapping("/myPage")
public String myPage(Model model) {
// 向模型中添加一个名为"message"的变量,其值为"Hello, Thymeleaf!"
model.addAttribute("message", "Hello, Thymeleaf!");
// 返回视图的名称,通常是模板文件的名称(不包括文件扩展名)
return "myPage";
}
}
在这个例子中,model.addAttribute(“message”, “Hello, Thymeleaf!”);这行代码向模型中添加了一个名为message的变量,其值为Hello, Thymeleaf!。这个变量随后可以在名为myPage.html的Thymeleaf模板中被访问。
在Thymeleaf模板中使用变量
在myPage.html模板中,你可以使用${…}语法来访问这个变量:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>My Page</title>
</head>
<body>
<p th:text="${message}">Message will be here</p>
</body>
</html>
在这个模板中,<p th:text="${message}">Message will be here</p>
这行代码将<p>
标签的文本内容设置为模型中名为message的变量的值,即Hello, Thymeleaf!。注意,如果message变量在模型中不存在,则<p>
标签将显示其默认的文本内容(在这个例子中是Message will be here),但这通常是在开发过程中用于调试的,而在生产环境中应该确保所有必要的变量都已被设置。
注意事项
Thymeleaf模板不直接支持在模板中嵌入Java代码。如果你需要在模板中执行更复杂的逻辑,你可能需要考虑使用Thymeleaf的预处理(Preprocessing)或后处理(Postprocessing)功能,或者将逻辑移到控制器中。
始终确保在控制器中向模型添加所有必要的变量,以避免在模板中出现空值或默认值。
Thymeleaf的变量表达式(${…})非常强大,可以访问复杂的对象图、执行方法调用、进行条件判断和循环等。但是,请保持模板的简洁和可读性,避免在模板中进行过多的逻辑处理。
6.3.2.3 URL表达式
6.3.3 常用标签
常用的th标签如下:
标签 | 说明 | 示例 |
---|---|---|
th:id | 替换id | <input th:id="'xxx'+${collect.id}"/> |
th:text | 文本替换 | <p th:text="${collect.description}">description</p> |
th:utext | 支持html的文本替换 | <p th:utext="${htmlcontent}">conten</p> |
th:value | 属性赋值 | <input th:value="${user.name}"/> |
th:selected | selected选择框选中 | th:selected="(${xxx.id} == ${configObj.dd})" |
th:style | 设置样式 | th:style="'display:'+@{(${sitrue}?'none':'inline-block')}+''" |
th:onclick | 点击事件 | th:onclick="'getCollect()'" |
th:action | 表单提交的地址 | <form action="subscribe.html" th:action="@{/subscribe}"> |
th:src | 图片类地址引入 | <img class="img-responsive" alt="App Logo" th:src="@{/img/logo.png}"/> |
th:href | 链接地址 | <a th:href="@{/login}" th:unless=${session.user != null}>Login</a> |
th:object | 替换对象 | <div th:object="${session.user}"> |
th:with | 变量赋值运算 | <div th:with="isEven=${prodStat.count}%2==0"></div> |
th:remove | 删除某个属性 | <tr:remove="all"> 1. all:删除包含标签和所有的子节点;2.body:不包含标记删除,但删除其所有的子节点;3.tag:包含标记的删除,但不删除它的子节点;4.all-but-first:删除所有包含标签的子节点,除了第一个。5.none:什么也不做。这个值是有用的动态评估 |
th:if | 判断条件 | <a th:if="${userId == collect.userId}"> |
th:unless | 和 th:if 判断相反 | <a th:href="@{/login}" th:unless=${session.user != null}>Login</a> |
th:switch | 多路选择配合th:case使用 | <div th:switch="${user.role}"> |
th:case | th:switch的一个分支 | <p th:case="'admin'">User is an administrator</p> |
th:each | 循环遍历 | <tr th:each="user,userStat:${users}"> |
th:fragment | 布局标签,定义一个代码片段,方便其他地方引用 | <div th:fragment="alert"> |
th:insert | 布局标签,加载整个标签到引入的文件 | <div th:insert="fragments/header::title"></div> |
th:replace | 布局标签,替换整个标签到引入的文件 | <div th:replace="fragments/header::title"></div> |
以上标签,前面部分基本和HTML标签对应,中间的th:object、th:with、th:remove几个和数据有关,再往下是一些逻辑控制标签,最后是布局标签。
6.3.3.1 条件判断 if/unless
在Thymeleaf中,你不能直接在模板中编写Java代码,因为Thymeleaf是一个用于Web和独立环境的现代服务器端Java模板引擎,它主要用于处理HTML、XML、JavaScript、CSS甚至纯文本。然而,你可以使用Thymeleaf的表达式语言(Thymeleaf Expression Language, Thymeleaf EL)来执行条件判断,这类似于Java中的if/else逻辑,但使用的是Thymeleaf的语法。
对于条件判断,Thymeleaf提供了th:if和th:unless属性。th:if用于在满足条件时包含或渲染某个元素,而th:unless则用于在不满足条件时包含或渲染某个元素。
示例
假设你有一个用户对象user,并且你想根据用户的角色来显示不同的内容。
HTML模板(使用Thymeleaf):
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>条件判断示例</title>
</head>
<body>
<div th:if="${user.role == 'ADMIN'}">
<p>欢迎管理员!</p>
</div>
<div th:unless="${user.role == 'ADMIN'}">
<p>欢迎普通用户!</p>
</div>
<!-- 更复杂的条件判断 -->
<div th:if="${user.role == 'ADMIN' and #lists.size(user.permissions) > 0}">
<p>管理员且拥有权限。</p>
</div>
<!-- 使用Thymeleaf的#lists工具类进行条件判断 -->
<div th:if="${not #lists.isEmpty(user.permissions)}">
<p>用户拥有权限。</p>
</div>
</body>
</html>
在这个例子中,th:if和th:unless属性用于根据user.role的值来显示不同的段落。th:if检查用户是否是管理员,而th:unless则检查用户是否不是管理员。
此外,还展示了如何使用Thymeleaf的内置工具类(如#lists)来进行更复杂的条件判断,比如检查用户权限列表是否为空。
注意
- Thymeleaf模板中的表达式(如${user.role == ‘ADMIN’})是Thymeleaf表达式语言(Thymeleaf EL)的一部分,而不是Java代码。
- 模板中的变量(如user)通常是由后端控制器(如Spring MVC中的Controller)传递到模板引擎的模型(Model)中的。
- Thymeleaf还提供了其他条件属性,如th:switch和th:case,用于实现更复杂的条件逻辑。
6.3.3.2 switch选择
在Thymeleaf中,并没有直接对应于Java中的switch语句的模板属性。但是,你可以通过组合使用th:if、th:unless或th:switch(尽管th:switch不是直接对应Java的switch,但它提供了一种基于多个条件选择性地渲染模板片段的方法)来实现类似switch的功能。
然而,重要的是要注意,Thymeleaf的th:switch属性实际上并不直接支持多个case条件,而是要求你为每个可能的值或条件使用一个嵌套的th:case(尽管这在技术上并不是th:switch的直接子属性,但它是通过在同一元素上组合使用来模拟switch行为的)。但是,由于th:case不能直接应用于th:switch之外的值,因此通常的做法是使用th:switch结合th:case=“*”(作为默认情况)和th:if(或th:unless)来模拟更复杂的switch逻辑。
不过,对于大多数情况,简单的th:if和th:unless组合应该就足够了。但如果你确实需要模拟switch的行为,下面是一个简化的例子,说明如何使用th:if(或更接近于你想要的th:switch和th:case的替代方法):
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Thymeleaf 模拟 Switch</title>
</head>
<body>
<div th:with="userRole=${user.role}">
<!-- 使用 th:if 模拟 switch -->
<p th:if="${userRole == 'ADMIN'}">管理员页面</p>
<p th:if="${userRole == 'USER'}">用户页面</p>
<p th:if="${userRole == 'GUEST'}">访客页面</p>
<!-- 可以添加一个默认情况 -->
<p th:unless="${#strings.contains(['ADMIN', 'USER', 'GUEST'], userRole)}">未知角色</p>
</div>
<!-- 注意:上面的 th:unless 并不是 th:switch 的一部分,但它用于模拟默认情况 -->
<!-- 实际上,Thymeleaf 没有直接的 th:switch-th:case 结构,但你可以通过上面的方式实现类似的功能 -->
</body>
</html>
在这个例子中,我们使用了th:with来在模板中创建一个局部变量userRole,以便我们可以多次引用它而不必每次都写${user.role}。然后,我们使用了一系列的th:if来检查userRole的值,并相应地渲染不同的段落。最后,我们使用了一个th:unless来捕捉任何未明确列出的角色,并显示一个默认消息。
如果你确实需要更复杂的条件逻辑,并且想要更接近Java中switch语句的语义,你可能需要在后端控制器中处理这些逻辑,并将结果作为模型属性传递给Thymeleaf模板,然后在模板中简单地显示结果。
6.3.3.3 for循环
在Thymeleaf中,你不能直接在模板中编写Java代码,包括Java的for循环。但是,Thymeleaf提供了自己的迭代(循环)机制,它允许你遍历集合、数组或任何可迭代对象,并基于每个元素渲染模板的某部分。
Thymeleaf使用th:each属性来实现迭代。这个属性可以应用于任何HTML元素,并且需要指定一个或多个迭代变量。
下面是一个使用th:each来遍历Java集合(例如List)并在Thymeleaf模板中渲染每个元素的例子:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Thymeleaf For Loop Example</title>
</head>
<body>
<h2>用户列表</h2>
<ul>
<!-- 假设有一个名为users的List集合,包含User对象 -->
<li th:each="user : ${users}">
<span th:text="${user.name}">用户名</span> -
<span th:text="${user.email}">用户邮箱</span>
</li>
</ul>
</body>
</html>
在这个例子中,th:each="user : $
{users}"是迭代的关键。这里,users是模型(Model)中传递给模板的List集合,而user是迭代过程中的当前元素(在这个例子中是User对象)的别名。在th:each所应用的元素(这里是<li>
)内部,你可以使用$
{user.name}和$
user.email}来访问当前User对象的属性。
在Spring MVC中,这个users集合可能是由你的控制器(Controller)添加到模型中的,如下所示:
@GetMapping("/users")
public String listUsers(Model model) {
List<User> users = userService.findAll(); // 假设这是你的服务层方法,用于获取所有用户
model.addAttribute("users", users); // 将用户列表添加到模型中
return "users"; // 返回模板的名称,Thymeleaf将使用这个名称来查找并渲染相应的HTML模板
}
请注意,虽然这个例子中的迭代看起来像是一个“for循环”,但实际上它是基于Thymeleaf的模板引擎机制实现的,与Java中的for循环在技术上是不同的。然而,从逻辑上讲,它们都能达到遍历集合并处理每个元素的目的。
原文地址:https://blog.csdn.net/2301_78884095/article/details/142402889
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!