本文目录导读:

- 项目结构
- Maven依赖 (pom.xml)
- 配置文件 (application.yml)
- 主类 (ThymeleafApplication.java)
- 模型类
- Service层
- Controller层
- Thymeleaf模板
我来为您提供一个完整的Spring Boot整合Thymeleaf的详细案例。
项目结构
spring-boot-thymeleaf-demo/
├── src/main/java/com/example/thymeleaf/
│ ├── ThymeleafApplication.java
│ ├── controller/
│ │ ├── UserController.java
│ │ └── PageController.java
│ ├── model/
│ │ ├── User.java
│ │ └── Product.java
│ └── service/
│ └── UserService.java
├── src/main/resources/
│ ├── static/
│ │ ├── css/
│ │ │ └── style.css
│ │ └── js/
│ │ └── main.js
│ ├── templates/
│ │ ├── index.html
│ │ ├── user/
│ │ │ ├── list.html
│ │ │ └── detail.html
│ │ └── fragments/
│ │ ├── header.html
│ │ └── footer.html
│ └── application.yml
└── pom.xml
Maven依赖 (pom.xml)
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.14</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>spring-boot-thymeleaf-demo</artifactId>
<version>1.0.0</version>
<name>spring-boot-thymeleaf-demo</name>
<description>Spring Boot整合Thymeleaf示例</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- Thymeleaf extras(可选,用于更高级功能) -->
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>
<!-- Lombok(可选,用于简化代码) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- Spring Boot DevTools(开发时热部署) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<!-- Spring Boot Test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
配置文件 (application.yml)
spring:
application:
name: spring-boot-thymeleaf-demo
thymeleaf:
# 模板缓存(开发环境设置为false)
cache: false
# 模板编码
encoding: UTF-8
# 模板模式
mode: HTML
# 模板前缀
prefix: classpath:/templates/
# 模板后缀
suffix: .html
# 检查模板是否存在
check-template: true
# 检查模板位置
check-template-location: true
# 是否启用模板引擎
enabled: true
server:
port: 8080
主类 (ThymeleafApplication.java)
package com.example.thymeleaf;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ThymeleafApplication {
public static void main(String[] args) {
SpringApplication.run(ThymeleafApplication.class, args);
}
}
模型类
User.java
package com.example.thymeleaf.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
import java.util.List;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Long id;
private String name;
private String email;
private Integer age;
private String role;
private Boolean active;
private LocalDateTime createdAt;
private List<String> hobbies;
public User(Long id, String name, String email, Integer age, String role, Boolean active) {
this.id = id;
this.name = name;
this.email = email;
this.age = age;
this.role = role;
this.active = active;
this.createdAt = LocalDateTime.now();
this.hobbies = Arrays.asList("读书", "运动", "编程");
}
}
Product.java
package com.example.thymeleaf.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product {
private Long id;
private String name;
private BigDecimal price;
private Integer stock;
private String category;
}
Service层
UserService.java
package com.example.thymeleaf.service;
import com.example.thymeleaf.model.User;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
@Service
public class UserService {
private List<User> users = new ArrayList<>();
@PostConstruct
public void init() {
User user1 = new User(1L, "张三", "zhangsan@example.com", 25, "管理员", true);
user1.setCreatedAt(LocalDateTime.now().minusDays(10));
user1.setHobbies(Arrays.asList("编程", "阅读", "游泳"));
User user2 = new User(2L, "李四", "lisi@example.com", 30, "用户", true);
user2.setCreatedAt(LocalDateTime.now().minusDays(5));
user2.setHobbies(Arrays.asList("旅游", "摄影"));
User user3 = new User(3L, "王五", "wangwu@example.com", 28, "用户", false);
user3.setCreatedAt(LocalDateTime.now().minusDays(15));
user3.setHobbies(Arrays.asList("游戏", "电影", "美食"));
User user4 = new User(4L, "赵六", "zhaoliu@example.com", 35, "用户", true);
user4.setCreatedAt(LocalDateTime.now().minusDays(1));
user4.setHobbies(Arrays.asList("音乐", "舞蹈"));
users.addAll(Arrays.asList(user1, user2, user3, user4));
}
public List<User> getAllUsers() {
return users;
}
public Optional<User> getUserById(Long id) {
return users.stream()
.filter(user -> user.getId().equals(id))
.findFirst();
}
public List<User> searchUsers(String keyword) {
if (keyword == null || keyword.isEmpty()) {
return users;
}
return users.stream()
.filter(user -> user.getName().contains(keyword) ||
user.getEmail().contains(keyword))
.collect(Collectors.toList());
}
public void addUser(User user) {
user.setId((long) (users.size() + 1));
user.setCreatedAt(LocalDateTime.now());
users.add(user);
}
}
Controller层
PageController.java
package com.example.thymeleaf.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Controller
public class PageController {
@GetMapping("/")
public String index(Model model) {
model.addAttribute("title", "Spring Boot Thymeleaf 示例");
model.addAttribute("message", "欢迎使用 Thymeleaf 模板引擎");
model.addAttribute("currentYear", java.time.Year.now().getValue());
return "index";
}
@GetMapping("/fragments")
public String fragments(Model model) {
model.addAttribute("title", "Thymeleaf 片段示例");
return "fragments-demo";
}
@GetMapping("/expressions")
public String expressions(Model model) {
// 字符串
model.addAttribute("str1", "Hello");
model.addAttribute("str2", "Thymeleaf");
// 数字
model.addAttribute("num1", 100);
model.addAttribute("num2", 20);
// 条件
model.addAttribute("age", 25);
model.addAttribute("isAdmin", true);
// 空值测试
model.addAttribute("nullValue", null);
model.addAttribute("emptyString", "");
// 列表
List<String> fruits = Arrays.asList("苹果", "香蕉", "橙子", "葡萄");
model.addAttribute("fruits", fruits);
// Map
Map<String, String> map = new HashMap<>();
map.put("key1", "value1");
map.put("key2", "value2");
model.addAttribute("map", map);
return "expressions";
}
}
UserController.java
package com.example.thymeleaf.controller;
import com.example.thymeleaf.model.User;
import com.example.thymeleaf.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
@Controller
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping
public String list(@RequestParam(required = false) String keyword, Model model) {
model.addAttribute("users", userService.searchUsers(keyword));
model.addAttribute("keyword", keyword);
model.addAttribute("totalUsers", userService.getAllUsers().size());
model.addAttribute("activeUsers", userService.getAllUsers().stream()
.filter(User::getActive).count());
return "user/list";
}
@GetMapping("/{id}")
public String detail(@PathVariable Long id, Model model) {
userService.getUserById(id).ifPresent(user ->
model.addAttribute("user", user));
return "user/detail";
}
@GetMapping("/add")
public String addForm(Model model) {
model.addAttribute("user", new User());
return "user/add";
}
@PostMapping("/add")
public String addUser(@ModelAttribute User user) {
userService.addUser(user);
return "redirect:/users";
}
@GetMapping("/conditional")
public String conditionalDemo(Model model) {
List<User> users = userService.getAllUsers();
model.addAttribute("users", users);
// 单个用户对象用于条件判断
model.addAttribute("adminUser", users.stream()
.findFirst().orElse(null));
return "user/conditional";
}
@GetMapping("/iteration")
public String iterationDemo(Model model) {
model.addAttribute("users", userService.getAllUsers());
return "user/iteration";
}
}
Thymeleaf模板
templates/index.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">th:text="${title}">首页</title>
<link rel="stylesheet" th:href="@{/css/style.css}">
</head>
<body>
<div th:replace="~{fragments/header :: header}"></div>
<main class="container">
<h1 th:text="${title}">Thymeleaf标题</h1>
<p th:text="${message}">消息内容</p>
<div class="card">
<h2>Thymeleaf 功能列表</h2>
<ul>
<li><a th:href="@{/expressions}">表达式示例</a></li>
<li><a th:href="@{/users}">用户列表(迭代与条件判断)</a></li>
<li><a th:href="@{/fragments}">片段引用示例</a></li>
<li><a th:href="@{/users/conditional}">条件判断示例</a></li>
<li><a th:href="@{/users/iteration}">循环遍历示例</a></li>
<li><a th:href="@{/users/add}">添加用户(表单处理)</a></li>
</ul>
</div>
<footer>
<p>© <span th:text="${currentYear}">年份</span> Spring Boot Thymeleaf Demo</p>
</footer>
</main>
<div th:replace="~{fragments/footer :: footer}"></div>
</body>
</html>
templates/user/list.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">用户列表</title>
<link rel="stylesheet" th:href="@{/css/style.css}">
</head>
<body>
<div th:replace="~{fragments/header :: header}"></div>
<main class="container">
<h1>用户列表</h1>
<!-- 统计信息 -->
<div class="stats">
<div class="stat-item">
<span>总用户数:</span>
<strong th:text="${totalUsers}">0</strong>
</div>
<div class="stat-item">
<span>活跃用户:</span>
<strong th:text="${activeUsers}">0</strong>
</div>
</div>
<!-- 搜索表单 -->
<form th:action="@{/users}" method="get" class="search-form">
<input type="text" name="keyword" th:value="${keyword}" placeholder="搜索用户名或邮箱...">
<button type="submit">搜索</button>
<a th:href="@{/users}" th:if="${keyword}">清除搜索</a>
</form>
<!-- 用户表格 -->
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>姓名</th>
<th>邮箱</th>
<th>年龄</th>
<th>角色</th>
<th>状态</th>
<th>创建时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<!-- 空数据判断 -->
<tr th:if="${#lists.isEmpty(users)}">
<td colspan="8" class="text-center">没有找到用户</td>
</tr>
<tr th:each="user, stat : ${users}" th:class="${stat.odd} ? 'odd' : 'even'">
<td th:text="${user.id}">1</td>
<td>
<a th:href="@{/users/{id}(id=${user.id})}"
th:text="${user.name}">姓名</a>
</td>
<td th:text="${user.email}">邮箱</td>
<td th:text="${user.age}">年龄</td>
<td>
<span th:if="${user.role == '管理员'}" class="badge badge-warning"
th:text="${user.role}">角色</span>
<span th:unless="${user.role == '管理员'}" class="badge badge-info"
th:text="${user.role}">角色</span>
</td>
<td>
<span th:if="${user.active}" class="status-active">● 活跃</span>
<span th:unless="${user.active}" class="status-inactive">○ 禁用</span>
</td>
<td th:text="${#temporals.format(user.createdAt, 'yyyy-MM-dd HH:mm')}">创建时间</td>
<td>
<a th:href="@{/users/{id}(id=${user.id})}" class="btn btn-small">详情</a>
</td>
</tr>
</tbody>
</table>
</main>
<div th:replace="~{fragments/footer :: footer}"></div>
</body>
</html>
templates/user/detail.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">用户详情 - <span th:text="${user.name}">姓名</span></title>
<link rel="stylesheet" th:href="@{/css/style.css}">
</head>
<body>
<div th:replace="~{fragments/header :: header}"></div>
<main class="container">
<h1>用户详情</h1>
<div th:if="${user}" class="user-detail">
<h2 th:text="${user.name}">姓名</h2>
<div class="detail-grid">
<div class="detail-item">
<label>ID:</label>
<span th:text="${user.id}">1</span>
</div>
<div class="detail-item">
<label>邮箱:</label>
<span th:text="${user.email}">email@example.com</span>
</div>
<div class="detail-item">
<label>年龄:</label>
<span th:text="${user.age}">25</span>
</div>
<div class="detail-item">
<label>角色:</label>
<span th:text="${user.role}">用户</span>
</div>
<div class="detail-item">
<label>状态:</label>
<span th:if="${user.active}" class="status-active">活跃</span>
<span th:unless="${user.active}" class="status-inactive">禁用</span>
</div>
<div class="detail-item">
<label>创建时间:</label>
<span th:text="${#temporals.format(user.createdAt, 'yyyy-MM-dd HH:mm')}">时间</span>
</div>
</div>
<!-- 爱好列表 -->
<div>
<h3>个人爱好</h3>
<ul>
<li th:each="hobby : ${user.hobbies}" th:text="${hobby}">爱好</li>
</ul>
</div>
<div class="actions">
<a th:href="@{/users}" class="btn">返回列表</a>
<a th:href="@{/users/add}" class="btn btn-primary">添加用户</a>
</div>
</div>
<div th:if="${user == null}" class="alert">
未找到该用户
</div>
</main>
<div th:replace="~{fragments/footer :: footer}"></div>
</body>
</html>
templates/user/add.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">添加用户</title>
<link rel="stylesheet" th:href="@{/css/style.css}">
</head>
<body>
<div th:replace="~{fragments/header :: header}"></div>
<main class="container">
<h1>添加用户</h1>
<form th:action="@{/users/add}" th:object="${user}" method="post" class="form">
<div class="form-group">
<label>姓名:</label>
<input type="text" th:field="*{name}" required>
</div>
<div class="form-group">
<label>邮箱:</label>
<input type="email" th:field="*{email}" required>
</div>
<div class="form-group">
<label>年龄:</label>
<input type="number" th:field="*{age}" min="1" max="120" required>
</div>
<div class="form-group">
<label>角色:</label>
<select th:field="*{role}">
<option value="用户">用户</option>
<option value="管理员">管理员</option>
<option value="审计员">审计员</option>
</select>
</div>
<div class="form-group">
<label>状态:</label>
<input type="checkbox" th:field="*{active}">
<span>启用</span>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">保存</button>
<a th:href="@{/users}" class="btn">取消</a>
</div>
</form>
</main>
<div th:replace="~{fragments/footer :: footer}"></div>
</body>
</html>
templates/fragments/header.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">Header</title>
</head>
<body>
<header th:fragment="header" class="header">
<nav class="nav">
<div class="nav-brand">
<a th:href="@{/}">
<span class="brand-icon">🚀</span>
Spring Boot Demo
</a>
</div>
<div class="nav-links">
<a th:href="@{/}" th:classappend="${currentPage == 'home'} ? 'active'">首页</a>
<a th:href="@{/users}" th:classappend="${currentPage == 'users'} ? 'active'">用户管理</a>
<a th:href="@{/expressions}">表达式</a>
<a th:href="@{/fragments}">片段</a>
</div>
</nav>
<div th:if="${#authorization == null}" class="navbar-user">
<span>欢迎访问</span>
</div>
</header>
</body>
</html>
templates/fragments/footer.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">Footer</title>
</head>
<body>
<footer th:fragment="footer" class="footer">
<div class="container">
<p>© <span th:text="${#temporals.year(#temporals.createNow())}">年份</span>
Spring Boot Thymeleaf Demo. All rights reserved.</p>
</div>
</footer>
</body>
</html>
templates/expressions.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">表达式示例</title>
<link rel="stylesheet" th:href="@{/css/style.css}">
</head>
<body>
<div th:replace="~{fragments/header :: header}"></div>
<main class="container">
<h1>Thymeleaf 表达式示例</h1>
<!-- 变量表达式 -->
<div class="card">
<h2>变量表达式 ${...}</h2>
<p>字符串1:<span th:text="${str1}">str1</span></p>
<p>字符串2:<span th:text="${str2}">str2</span></p>
<p>数字1:<span th:text="${num1}">100</span></p>
<p>数字2:<span th:text="${num2}">20</span></p>
</div>
<!-- 选择表达式 -->
<div class="card">
<h2>选择表达式 *{...} 结合 th:object</h2>
<div th:object="${user != null} ? ${user} : null">
<!-- 这里使用 *{} 访问 user 的属性 -->
<p>名称:<span th:text="*{name}">名称</span></p>
</div>
<div th:with="user=${users != null && !#lists.isEmpty(users)} ? ${users[0]} : null"
th:object="${user}">
<p>名称(通过object):<span th:text="*{name}">名称</span></p>
</div>
</div>
<!-- URL表达式 -->
<div class="card">
<h2>URL表达式 @{...}</h2>
<ul>
<li><a th:href="@{/}">首页</a></li>
<li><a th:href="@{/users}">用户列表</a></li>
<li><a th:href="@{/users/{id}(id=1)}">用户详情</a></li>
<li><a th:href="@{/users/page(p=0,s=10)}">带参数链接</a></li>
</ul>
</div>
<!-- 条件判断 -->
<div class="card">
<h2>条件运算</h2>
<p>三目运算:<span th:text="${age >= 18} ? '成年人' : '未成年人'">判断结果</span></p>
<p>空安全运算符 (?:):<span th:text="${nullValue ?: '默认值'}">默认值</span></p>
<p>判断空字符串:<span th:if="${#strings.isEmpty(emptyString)}">空字符串</span></p>
</div>
<!-- 内联表达式 -->
<div class="card">
<h2>内联表达式</h2>
<p th:inline="text">你好,[[${str1}]] [[${str2}]]!</p>
<p th:inline="css">[[${str1}]]</p>
</div>
<!-- 运算示例 -->
<div class="card">
<h2>数学运算</h2>
<p>加法:<span th:text="${num1} + ${num2}">结果</span></p>
<p>减法:<span th:text="${num1} - ${num2}">结果</span></p>
<p>乘法:<span th:text="${num1} * ${num2}">结果</span></p>
<p>除法:<span th:text="${num1} / ${num2}">结果</span></p>
<p>取模:<span th:text="${num1} % ${num2}">结果</span></p>
</div>
<!-- 列表操作 -->
<div class="card">
<h2>集合操作</h2>
<ul>
<li th:each="fruit, stat : ${fruits}"
th:with="fruitInfo=${fruit}">
<span th:text="${fruit}">水果</span>
<span th:text="'(' + ${stat.index} + ')'" th:if="${stat.first}">(第一个)</span>
<span th:text="'(' + ${stat.count} + ')'" th:unless="${stat.first}">(其他)</span>
</li>
</ul>
</div>
</main>
<div th:replace="~{fragments/footer :: footer}"></div>
</body>
</html>
templates/user/conditional.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">条件判断示例</title>
<link rel="stylesheet" th:href="@{/css/style.css}">
</head>
<body>
<div th:replace="~{fragments/header :: header}"></div>
<main class="container">
<h1>Thymeleaf 条件判断示例</h1>
<!-- 基本条件判断 -->
<div class="card">
<h2>基本 if/unless</h2>
<div th:if="${adminUser != null}">
<p>管理员信息:<span th:text="${adminUser.name}">名称</span></p>
</div>
<div th:unless="${adminUser == null}">
<p>当前有管理员用户</p>
</div>
</div>
<!-- switch-case -->
<div class="card">
<h2>switch-case 示例</h2>
<div th:switch="${adminUser.role}">
<p th:case="'管理员'" th:text="'角色:' + ${adminUser.role}">管理员</p>
<p th:case="'用户'" th:text="'角色:' + ${adminUser.role}">用户</p>
<p th:case="*" th:text="'未知角色:' + ${adminUser.role}">其他角色</p>
</div>
</div>
<!-- 列表条件判断 -->
<div class="card">
<h2>结合循环的条件判断</h2>
<table class="table">
<thead>
<tr>
<th>姓名</th>
<th>角色</th>
<th>状态</th>
<th>年龄判断</th>
</tr>
</thead>
<tbody>
<tr th:each="user : ${users}">
<td th:text="${user.name}">姓名</td>
<td>
<span th:switch="${user.role}">
<span th:case="'管理员'" class="badge badge-danger" th:text="${user.role}">管理员</span>
<span th:case="'用户'" class="badge badge-info" th:text="${user.role}">用户</span>
<span th:case="*" th:text="${user.role}">其他</span>
</span>
</td>
<td>
<span th:if="${user.active}" class="text-success">✅ 激活</span>
<span th:if="${!user.active}" class="text-danger">❌ 禁止</span>
</td>
<td>
<span th:if="${user.age >= 30}" th:text="'30岁以上的用户'">>=30</span>
<span th:if="${user.age >= 25 && user.age < 30}" th:text="'25-29岁'">25-29</span>
<span th:if="${user.age < 25}" th:text="'25岁以下'"><25</span>
</td>
</tr>
</tbody>
</table>
</div>
<!-- 空值判断 -->
<div class="card">
<h2>空值判断</h2>
<p th:if="${#lists.isEmpty(users)}">用户列表为空</p>
<p th:if="${!#lists.isEmpty(users)}">用户列表不为空</p>
</div>
</main>
<div th:replace="~{fragments/footer :: footer}"></div>
</body>
</html>
templates/user/iteration.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">循环遍历示例</title>
<link rel="stylesheet" th:href="@{/css/style.css}">
</head>
<body>
<div th:replace="~{fragments/header :: header}"></div>
<main class="container">
<h1>Thymeleaf 循环遍历示例</h1>
<!-- 基本循环 -->
<div class="card">
<h2>基本循环遍历</h2>
<h3>用户列表:</h3>
<ul>
<li th:each="user : ${users}"
th:text="${user.name} + ' - ' + ${user.email}">
用户信息
</li>
</ul>
</div>
<!-- 带状态的循环 -->
<div class="card">
<h2>带循环状态的遍历</h2>
<ul>
<li th:each="user, stat : ${users}">
<div class="user-item">
<span class="index" th:text="'#' + ${stat.index}">索引</span>
<span th:text="${user.name}">姓名</span>
<span class="badge"
th:if="${stat.first}"
th:text="'(第一个)'">第一个</span>
<span class="badge"
th:if="${stat.last}"
th:text="'(最后一个)'">最后一个</span>
<span class="badge badge-odd"
th:if="${stat.odd}"
th:text="'(奇数')">奇数</span>
<span class="badge badge-even"
th:if="${stat.even}"
th:text="'(偶数)'">偶数</span>
<span th:text="'大小:' + ${stat.size}">大小</span>
</div>
</li>
</ul>
</div>
<!-- 循环属性访问 -->
<div class="card">
<h2>搭配条件和状态的操作</h2>
<table class="table">
<thead>
<tr>
<th>#</th>
<th>姓名</th>
<th>角色</th>
<th>状态</th>
</tr>
</thead>
<tbody>
<tr th:each="user, rowStat : ${users}"
th:class="${rowStat.odd} ? 'row-odd' : 'row-even'">
<td th:text="${rowStat.count}">序号</td>
<td th:text="${user.name}">姓名</td>
<td>
<span th:text="${user.role}">角色</span>
<span th:if="${user.role == '管理员'}" class="badge">⭐ 管理员</span>
</td>
<td>
<span th:text="${user.active ? '活跃' : '禁止'}">状态</span>
</td>
</tr>
</tbody>
</table>
</div>
<!-- 嵌套循环 -->
<div class="card">
<h2>嵌套循环示例</h2>
<div th:each="user : ${users}">
<strong th:text="${user.name} + ' 的爱好:'">爱好</strong>
<ul>
<li th:each="hobby : ${user.hobbies}" th:text="${hobby}">爱好</li>
</ul>
<hr
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播