导读:本期聚焦于葵司创作的《Spring Boot 整合 Thymeleaf 实现前后端不分离开发模式怎么做?》,敬请观看详情。页面渲染到底该放在服务端还是浏览器端?当项目规模不大、团队人手有限时,前后端不分离往往开发效率更高。本文围绕 Spring Boot 整合 Thymeleaf 这一经典方案展开,从依赖引入、配置文件设置讲起,逐步演示控制器与模板页面如何配合完成数据渲染,涵盖变量输出、条件判断、循环遍历、表单提交与数据回显等常用语法,并补充静态资源处理、热部署配置以及常见报错的排查思路,帮你快速搭建一套完整的模板渲染开发流程。

在微服务和前后端分离大行其道的今天,服务端模板渲染依然有它不可替代的场景。内部管理系统、小型企业官网、原型验证项目,这类项目对交互要求不高,用一套 Thymeleaf 模板就能把页面和数据一起搞定,省去了前端工程化、接口联调、跨域配置等一系列麻烦。Spring Boot 对 Thymeleaf 的支持开箱即用,整合成本极低,本文就完整走一遍从零搭建到页面渲染的流程。

Spring Boot 整合 Thymeleaf 实现前后端不分离开发模式怎么做?

引入依赖与基础配置

整合的第一步是在 pom.xml 中加入 Thymeleaf 的 starter 依赖。Spring Boot 会自动完成大部分装配工作,开发者几乎不需要写任何配置类。

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

这个 starter 内部已经包含了 spring-boot-starter-web,所以不需要重复引入 web 依赖。依赖加进来之后,Thymeleaf 的默认约定是到 classpath:/templates/ 目录下寻找模板文件,到 classpath:/static/ 目录下寻找静态资源,这个约定优先于配置,只有确实需要调整时才在 application.yml 中显式声明。

虽然默认约定已经够用,但了解几个常用配置项仍然有价值,比如开发期关闭缓存让页面修改即时生效,生产环境再打开:

spring:
  thymeleaf:
    cache: false          # 开发环境关闭模板缓存
    encoding: UTF-8       # 模板编码
    mode: HTML            # 模板模式
    prefix: classpath:/templates/
    suffix: .html

这里最容易踩的坑是 cache: false 忘记改回 true 就上了生产环境。模板缓存关闭意味着每次请求都要重新解析模板,高并发下会带来明显的性能损耗。建议通过多环境配置(dev 和 prod 分开)来管理这个开关,避免手滑。

编写控制器与模板页面

配置完成后,接下来看控制器和模板如何配合。控制器负责准备数据并指定视图名,Thymeleaf 负责把数据填充进模板渲染出最终 HTML。先写一个简单的 Controller:

@Controller
public class UserController {

    @GetMapping("/users")
    public String listUsers(Model model) {
        List<User> users = new ArrayList<>();
        users.add(new User(1L, "张三", "zhangsan@ipipp.com"));
        users.add(new User(2L, "李四", "lisi@ipipp.com"));
        model.addAttribute("userList", users);
        model.addAttribute("title", "用户列表");
        return "user/list";   // 对应 templates/user/list.html
    }
}

注意这里的 @Controller 不能误写成 @RestController,后者会把返回值直接当作响应体输出,浏览器拿到的就是一段字符串而不是渲染后的页面。返回的视图名 user/list 会拼接上配置中的前缀和后缀,最终定位到 templates/user/list.html 文件。

模板页面这边,需要在 html 标签上声明 Thymeleaf 的命名空间,这样 IDE 才能提供语法提示:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title th:text="${title}">默认标题</title>
</head>
<body>
    <h1 th:text="${title}">用户管理</h1>
    <table border="1">
        <tr>
            <th>ID</th><th>姓名</th><th>邮箱</th>
        </tr>
        <tr th:each="user : ${userList}">
            <td th:text="${user.id}">1</td>
            <td th:text="${user.name}">张三</td>
            <td th:text="${user.email}">test@ipipp.com</td>
        </tr>
    </table>
</body>
</html>

这个例子体现了 Thymeleaf 最讨人喜欢的特性:原型可用。标签里写的静态内容(比如“张三”)在没有数据时也能正常显示,设计师拿到的 HTML 可以直接在浏览器里打开预览,加上 th:* 属性后就变成了动态模板,前后协作时沟通成本大大降低。

常用语法:变量、条件与内联表达式

除了 th:textth:each,日常开发中还有几组高频语法必须掌握。th:ifth:unless 控制元素是否渲染,th:switch 处理多分支,th:object 配合 *{} 表达式可以简化对象属性的访问。

<div th:object="${user}">
    <p>姓名:<span th:text="*{name}">--</span></p>
    <p th:if="*{vip}">会员标识:VIP 用户</p>
    <p th:unless="*{vip}">普通用户</p>
</div>

<!-- 内联写法,直接在文本中使用表达式 -->
<p>欢迎你,[[${user.name}]]</p>

内联表达式 [[...]] 在拼接少量动态文本时非常方便,避免了为了一个变量单独加 span 标签。需要注意 th:if 的判断逻辑与 Java 略有差异:非零数字、非空字符串、字符串 "false" 之外的值都会被判定为真,null 和零判定为假,写条件时要多留个心眼。

日期和数字的格式化也有现成工具,比如 th:text="${#dates.format(user.createTime, 'yyyy-MM-dd HH:mm')}" 可以直接格式化日期,不必在控制器里先转成字符串,保持模板表达式的简洁。

表单提交与数据回显

管理系统的核心场景之一就是表单。Thymeleaf 提供了 th:actionth:field 等属性来简化表单处理,其中 th:field 会自动生成 name 和 id 属性,并绑定了对应的数据回显。

<form th:action="@{/user/save}" th:object="${user}" method="post">
    <input type="text" th:field="*{name}" placeholder="请输入姓名"/>
    <input type="text" th:field="*{email}" placeholder="请输入邮箱"/>
    <button type="submit">提交</button>
</form>

对应的控制器需要提供 GET 和 POST 两个入口,GET 用于打开表单页(携带一个空对象用于回显),POST 用于接收提交:

@Controller
@RequestMapping("/user")
public class UserFormController {

    @GetMapping("/add")
    public String addPage(Model model) {
        model.addAttribute("user", new User());
        return "user/form";
    }

    @PostMapping("/save")
    public String save(@ModelAttribute User user) {
        // 保存逻辑省略
        return "redirect:/users";   // 提交成功后重定向到列表页
    }
}

提交成功后返回 redirect: 前缀的视图名是经典的最佳实践,重定向可以防止用户刷新页面时重复提交表单。而如果校验失败,直接返回原视图名,th:field 会自动把用户刚填的数据回显到表单里,用户体验比手写回显逻辑省心得多。

如果要提示错误信息,可以配合 Spring 的 BindingResult,在模板中用 th:errorsth:if="${#fields.hasErrors('name')}" 来逐字段展示校验失败原因,形成完整的表单闭环。

静态资源处理与常见问题排查

CSS、JS、图片等静态资源默认放在 src/main/resources/static 下,模板中引用时强烈建议使用 @{...} 链接表达式。如果项目配置了 context-path,或者后续部署到 Nginx 子路径下,写死的路径会全部失效,而 @{} 会自动带上应用上下文前缀:

<link rel="stylesheet" th:href="@{/css/style.css}"/>
<script th:src="@{/js/app.js}"></script>
<a th:href="@{/user/add}">新增用户</a>

开发过程中还有几个高频报错值得提前了解。一是 TemplateInputException,提示找不到模板,多半是视图名和文件路径对不上,或者文件后缀写成了 .htm、.tpl 之类的非默认后缀。二是页面输出乱码,检查 application.yml 中的 encoding 配置以及模板文件本身的保存编码是否为 UTF-8。三是修改模板不生效,九成是缓存没关,配置 cache: false 后重启即可;也可以额外引入 spring-boot-devtools 实现包括模板在内的资源热加载,进一步提升开发效率。

整体来看,Spring Boot 加 Thymeleaf 的组合胜在简单直接:数据流转清晰、SEO 友好、无需维护两套工程。只要页面交互不是特别复杂,这套前后端不分离的方案依然能打,掌握本文这些语法和排查手段,就足够支撑一个中型管理系统的页面开发需求了。

Spring BootThymeleaf前后端不分离修改时间:2026-09-08 11:13:05

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260908/52730.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。