实验二: Thymeleaf的使用
实验过程
- 引入 Thymeleaf 模板引擎
首先,在项目中引入 Thymeleaf 依赖,使 Spring Boot 支持模板渲染:
打开pom.xml文件
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
- 使项目能够解析
templates目录下的 HTML 文件 - 支持
th:*语法

- 调整项目结构
将原有静态页面从 static 目录移动到:
plain
src/main/resources/templates/
并将文件命名为:
plain
wuziqi.html
static→ 纯静态页面(不会走 Thymeleaf)templates→ 模板页面(由 Thymeleaf解析)

- 编写 Controller(核心步骤)
创建控制器 PageController,用于:
- 初始化棋盘
- 接收用户点击坐标
- 更新棋盘状态
- 判断胜负
- 向前端传递数据
完整代码文件:
java
package com.wuziqi.java.shiyan1.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.ArrayList;
import java.util.List;
@Controller
public class PageController {
private final List<List<Integer>> board = new ArrayList<>();
private int currentPlayer = 1;
private String winner = null;
@GetMapping("/game")
public String gamePage(
@RequestParam(required = false) Integer x,
@RequestParam(required = false) Integer y,
Model model) {
// 初始化
if (board.isEmpty()) {
for (int i = 0; i < 15; i++) {
List<Integer> row = new ArrayList<>();
for (int j = 0; j < 15; j++) {
row.add(0);
}
board.add(row);
}
}
// 落子(+胜负判断)
if (x != null && y != null && winner == null) {
if (board.get(x).get(y) == 0) {
board.get(x).set(y, currentPlayer);
// 胜负判断
if (win(x, y)) {
winner = currentPlayer == 1 ? "黑棋胜利!" : "白棋胜利!";
} else {
currentPlayer = 3 - currentPlayer;
}
}
}
model.addAttribute("board", board);
model.addAttribute("currentPlayer", currentPlayer == 1 ? "黑棋" : "白棋");
model.addAttribute("message", "欢迎你");
model.addAttribute("winner", winner);
return "wuziqi";
}
// 极简胜负判断
private boolean win(int x, int y) {
int p = board.get(x).get(y);
int[][] d = {{1,0},{0,1},{1,1},{1,-1}};
for (int[] dir : d) {
int count = 1;
for (int k = 1; k < 5; k++) {
int nx = x + dir[0]*k, ny = y + dir[1]*k;
if (nx<0||ny<0||nx>=15||ny>=15||board.get(nx).get(ny)!=p) break;
count++;
}
for (int k = 1; k < 5; k++) {
int nx = x - dir[0]*k, ny = y - dir[1]*k;
if (nx<0||ny<0||nx>=15||ny>=15||board.get(nx).get(ny)!=p) break;
count++;
}
if (count >= 5) return true;
}
return false;
}
}
核心代码逻辑
(1)初始化棋盘
java
if (board.isEmpty()) {
for (int i = 0; i < 15; i++) {
List<Integer> row = new ArrayList<>();
for (int j = 0; j < 15; j++) {
row.add(0);
}
board.add(row);
}
}
生成 15×15 棋盘
(2)处理点击落子
java
if (x != null && y != null && winner == null) {
if (board.get(x).get(y) == 0) {
board.get(x).set(y, currentPlayer);
}
}
根据点击坐标更新棋盘
(3)胜负判断
java
if (win(x, y)) {
winner = currentPlayer == 1 ? "黑棋胜利!" : "白棋胜利!";
}
判断是否形成五子连珠
(4)切换玩家
java
currentPlayer = 3 - currentPlayer;
黑白轮流
(5)向页面传递数据
java
model.addAttribute("board", board);
model.addAttribute("currentPlayer", ...);
model.addAttribute("message", "欢迎你");
model.addAttribute("winner", winner);
供 Thymeleaf 使用
- 编写 Thymeleaf 页面
在 wuziqi.html 中使用 Thymeleaf 指令实现动态页面。
完整代码文件:
html
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>五子棋</title>
<style>
body {
text-align: center;
font-family: "Microsoft YaHei";
background: #f5e1b5;
}
.board {
position: relative;
width: 420px;
height: 420px;
margin: 30px auto;
background: #deb887;
}
/* 横线 */
.line-h {
position: absolute;
left: 0;
width: 100%;
height: 1px;
background: #333;
}
/* 竖线 */
.line-v {
position: absolute;
top: 0;
height: 100%;
width: 1px;
background: #333;
}
/* 交叉点 */
.point {
position: absolute;
width: 20px;
height: 20px;
transform: translate(-50%, -50%);
}
.point a {
display: block;
width: 100%;
height: 100%;
}
.piece {
width: 18px;
height: 18px;
border-radius: 50%;
margin: auto;
}
.black {
background: black;
}
.white {
background: white;
border: 1px solid #999;
}
</style>
</head>
<body>
<h1>五子棋</h1>
<h2 th:text="${message}"></h2>
<p>当前玩家:<span th:text="${currentPlayer}"></span></p>
<h2 th:if="${winner != null}"
th:text="${winner}"
style="color:red;"></h2>
<div class="board">
<!-- 横线 -->
<div th:each="i : ${#numbers.sequence(0,14)}"
class="line-h"
th:style="|top:${i * 30}px|"></div>
<!-- 竖线 -->
<div th:each="i : ${#numbers.sequence(0,14)}"
class="line-v"
th:style="|left:${i * 30}px|"></div>
<!-- 所有交叉点 -->
<div th:each="row,rowStat : ${board}">
<div th:each="cell,colStat : ${row}"
class="point"
th:style="|top:${rowStat.index * 30}px; left:${colStat.index * 30}px|">
<a th:href="@{/game(x=${rowStat.index}, y=${colStat.index})}">
<div th:if="${cell == 1}" class="piece black"></div>
<div th:if="${cell == 2}" class="piece white"></div>
</a>
</div>
</div>
</div>
</body>
</html>
(1)显示文本信息
html
<h2 th:text="${message}"></h2>
<p>当前玩家:<span th:text="${currentPlayer}"></span></p>
显示后端数据
(2)胜负提示
html
<h2 th:if="${winner != null}" th:text="${winner}"></h2>
条件显示胜利信息
(3)生成棋盘(双层循环)
html
<div th:each="row,rowStat : ${board}">
<div th:each="cell,colStat : ${row}">
根据二维数组动态生成棋盘
(4)棋子显示
html
<div th:if="${cell == 1}" class="black"></div>
<div th:if="${cell == 2}" class="white"></div>
判断显示黑棋或白棋
(5)点击落子(核心交互)
html
<a th:href="@{/game(x=${rowStat.index}, y=${colStat.index})}">
点击棋盘发送坐标到后端
(6)动态样式(定位棋盘)
html
th:style="|top:${rowStat.index * 30}px; left:${colStat.index * 30}px|"
计算每个交叉点位置
- 页面运行与测试
启动项目后,在浏览器访问:
plain
http://localhost:8080/game
介绍这个实验
一、Thymeleaf 是什么
Thymeleaf 是一种 Java Web 模板引擎,主要用于在服务器端将数据渲染到 HTML 页面中。用于将后端数据动态渲染到 HTML 页面中的模板引擎,实现了页面与数据的解耦。
简单理解:
- Controller 负责数据
Thymeleaf 负责把数据"填进 HTML"
核心特点
- 服务端渲染
- 页面在服务器生成后再返回浏览器
- HTML友好
- 页面本身仍然是合法HTML
- 使用 th: 语法操作数据
- 如
th:text、th:each、th:if
- 如
二、本项目整体说明
本项目实现了一个基于 Spring Boot 的五子棋游戏,主要结构如下:
- Controller(后端逻辑)
负责:
- 初始化棋盘
- 处理落子
- 判断胜负
- 向页面传递数据
例如:
java
model.addAttribute("board", board);
model.addAttribute("currentPlayer", ...);
model.addAttribute("message", "欢迎你");
model.addAttribute("winner", winner);
这些数据会被 Thymeleaf 使用
- HTML(前端模板)
负责:
- 显示棋盘
- 显示棋子
- 显示当前玩家、胜负结果
但不是写死的,而是通过 Thymeleaf 动态生成
- 数据流
plain
用户点击 → /game?x=..&y=..
→ Controller处理
→ Model传数据
→ Thymeleaf渲染HTML
→ 页面更新
三、项目中使用 Thymeleaf 的地方
- th:text(显示数据)
html
<h2 th:text="${message}"></h2>
<p>当前玩家:<span th:text="${currentPlayer}"></span></p>
- 把 Controller 传来的数据显示出来
举例
Controller:
java
model.addAttribute("message", "欢迎你");
页面:
html
<h2 th:text="${message}"></h2>
页面显示:欢迎你
- th:if(条件渲染)
html
<h2 th:if="${winner != null}" th:text="${winner}"></h2>
- 只有胜利时才显示文字
效果
| winner | 页面 |
|---|---|
| null | 不显示 |
| 黑棋胜利 | 显示 |
- th:each(循环渲染棋盘)
html
<div th:each="row,rowStat : ${board}">
<div th:each="cell,colStat : ${row}">
- 遍历二维数组(棋盘)
对应后端
java
List<List<Integer>> board
通过循环生成 15×15 棋盘
- th:style(动态样式)
html
th:style="|top:${rowStat.index * 30}px; left:${colStat.index * 30}px|"
- 根据坐标计算位置
- 实现棋盘"交叉点布局"
- th:href(点击落子)
html
<a th:href="@{/game(x=${rowStat.index}, y=${colStat.index})}">
- 点击棋盘时发送请求
- 把坐标传给 Controller
实际效果----点击某个点:
plain
/game?x=7&y=8
- th:if(棋子显示)
html
<div th:if="${cell == 1}" class="piece black"></div>
<div th:if="${cell == 2}" class="piece white"></div>
- 判断当前位置是什么棋子
- 决定显示黑棋还是白棋
总结:
本项目中使用了 Thymeleaf 模板引擎,实现了后端数据向前端页面的动态渲染。在控制器中通过 Model 传递棋盘数据、当前玩家和胜负信息,在 HTML 页面中通过 th:text、th:each、th:if、th:href 等指令实现数据展示、循环生成棋盘、条件渲染棋子以及点击交互。相比传统静态页面,Thymeleaf 能够实现页面与数据分离,提高代码的可维护性和动态性。