在传统的管理后台项目开发中,当选择前后端不分离的架构时,模板引擎是动态生成页面的关键技术。Thymeleaf以其“自然模板”特性著称,而FreeMarker则凭借高效与灵活深受开发者喜爱。本文将以一个典型的用户管理列表页为例,分别使用两种引擎进行实现,详细对比其语法特性与开发流程,为您的技术选型提供清晰参考。
一、项目准备:环境搭建与基础配置
1. 引入核心依赖
在基于 Spring Boot 的项目中,于 pom.xml 文件中引入Web基础依赖,并根据需要选择对应的模板引擎依赖。
<!-- 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>
<!-- FreeMarker依赖(二选一) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
2. 准备模拟数据与控制器
创建用户实体类及控制器,用于在后台模拟数据并传递给视图层进行渲染。
// 用户实体类
@Data
public class User {
private Long id;
private String username;
private String email;
private Integer age;
private String status; // 状态:ENABLE/DISABLE
}
// 后台控制器
@Controller
@RequestMapping("/admin")
public class AdminController {
@GetMapping("/users")
public String userList(Model model) {
// 模拟用户数据
List<User> userList = Arrays.asList(
new User(1L, "zhangsan", "zhangsan@example.com", 22, "ENABLE"),
new User(2L, "lisi", "lisi@example.com", 25, "DISABLE")
);
model.addAttribute("userList", userList);
model.addAttribute("title", "用户管理");
return "user/list"; // 对应模板文件路径
}
}
二、Thymeleaf实现:贴近前端的自然模板
Thymeleaf最大的特点是允许模板文件作为静态HTML直接在浏览器中预览,这极大地方便了前后端协作与页面样式的快速调整。
1. 创建模板文件
在 resources/templates/user/ 目录下创建 list.html 文件,并添加Thymeleaf命名空间。
<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title th:text="${title}">用户管理</title>
<style>
table {width: 80%; margin: 20px auto; border-collapse: collapse;}
th, td {border: 1px solid #ccc; padding: 8px; text-align: center;}
.enable {color: green;}
.disable {color: red;}
</style>
</head>
<body>
<h1 th:text="${title}" style="text-align: center;">用户管理</h1>
<table>
<thead>
<tr>
<th>ID</th>
<th>用户名</th>
<th>邮箱</th>
<th>年龄</th>
<th>状态</th>
</tr>
</thead>
<tbody>
<!-- 使用th:each进行数据遍历 -->
<tr th:each="user : ${userList}">
<td th:text="${user.id}"></td>
<td th:text="${user.username}"></td>
<td th:text="${user.email}"></td>
<td th:text="${user.age}"></td>
<!-- 使用条件表达式判断样式与显示文本 -->
<td th:class="${user.status == 'ENABLE' ? 'enable' : 'disable'}"
th:text="${user.status == 'ENABLE' ? '启用' : '禁用'}">
</td>
</tr>
</tbody>
</table>
</body>
</html>
2. 核心优势解析
- 自然模板:所有动态逻辑通过
th:* 属性(如 th:text, th:each)嵌入标准HTML中,未启动应用时也可看到静态骨架,便于设计与调试。
- 低侵入性:不破坏HTML文档结构,前端开发者无需学习新语法即可理解页面布局。
- 表达式强大:支持丰富的OGNL/SpringEL表达式,能直接在属性中完成条件判断、数据拼接等操作。
三、FreeMarker实现:简洁高效的逻辑处理
FreeMarker采用自有的模板语法,不依赖于HTML标签属性,在数据处理和复杂逻辑表达上更为直接灵活。
1. 基础配置与模板创建
可在 application.yml 中进行个性化配置(Spring Boot默认配置通常已足够)。
spring:
freemarker:
suffix: .ftl
template-loader-path: classpath:/templates/
charset: UTF-8
settings:
default_encoding: UTF-8
在 resources/templates/user/ 目录下创建 list.ftl 文件。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>${title!"用户管理"}</title>
<style>
table {width: 80%; margin: 20px auto; border-collapse: collapse;}
th, td {border: 1px solid #ccc; padding: 8px; text-align: center;}
.enable {color: green;}
.disable {color: red;}
</style>
</head>
<body>
<h1 style="text-align: center;">${title!"用户管理"}</h1>
<table>
<thead>
<tr>
<th>ID</th>
<th>用户名</th>
<th>邮箱</th>
<th>年龄</th>
<th>状态</th>
</tr>
</thead>
<tbody>
<!-- 使用#list指令遍历,支持#else处理空集合 -->
<#list userList as user>
<tr class="${(user.status == 'ENABLE')?string('enable', 'disable')}">
<td>${user.id}</td>
<td>${user.username}</td>
<td>${user.email}</td>
<td>${user.age}</td>
<td>${(user.status == 'ENABLE')?string('启用', '禁用')}</td>
</tr>
<#else>
<tr><td colspan="5">暂无用户数据</td></tr>
</#list>
</tbody>
</table>
</body>
</html>
2. 核心优势解析
- 空值安全处理:使用
${变量!"默认值"} 语法,能有效避免因变量为空导致的模板渲染错误。
- 指令简洁清晰:
<#list> 等指令专为逻辑控制设计,结构分明,尤其擅长处理复杂的数据遍历与条件分支。
- 灵活的函数与运算符:内置丰富的内建函数和运算符,方便在模板内进行字符串处理、数字计算等操作。
四、布局复用:统一管理后台界面
管理后台通常有统一的页头、侧边栏和页脚,两大模板引擎都提供了优秀的模块化方案。
1. Thymeleaf:片段(Fragment)引用
定义公共片段 resources/templates/common/layout.html:
<div th:fragment="header">
<div style="height: 50px; background: #333; color: #fff; line-height: 50px; text-align: center;">
后台管理系统
</div>
</div>
在页面中引用:
<div th:replace="~{common/layout :: header}"></div>
2. FreeMarker:宏(Macro)定义与导入
定义公共宏 resources/templates/common/macro.ftl:
<#macro header>
<div style="height: 50px; background: #333; color: #fff; line-height: 50px; text-align: center;">
后台管理系统
</div>
</#macro>
在页面中导入并使用:
<#import "/common/macro.ftl" as layout>
<@layout.header />
五、综合对比与选型建议
| 特性维度 |
Thymeleaf |
FreeMarker |
| 开发体验 |
静态HTML可直接预览,前后端协作顺畅 |
语法专注逻辑,后端开发者编写高效 |
| 空值处理 |
需借助?:等表达式手动处理 |
原生提供!“默认值”语法,便捷安全 |
| 布局复用 |
通过th:fragment和th:replace实现 |
通过<#macro>定义和<#import>导入实现 |
| 学习成本 |
较低,对前端友好,符合HTML习惯 |
中等,需记忆一套独立的模板指令 |
| 性能表现 |
良好,满足大多数应用场景 |
通常认为在复杂模板下性能略优 |
| 适用场景 |
中小型后台、需要频繁调样式的项目 |
逻辑复杂、数据模型多变的高要求后台 |
选型总结建议:
- 选择 Thymeleaf:如果你的团队具备前端技能,或项目处于快速原型迭代阶段,强调“所见即所得”的开发体验。
- 选择 FreeMarker:如果项目后台页面业务逻辑复杂,包含大量条件判断与数据转换,或者对模板渲染性能有极致要求。
六、核心结论
Thymeleaf与FreeMarker都是与 Spring Boot 集成度极高的优秀模板引擎。两者的根本差异源于设计哲学:Thymeleaf致力于成为HTML的优雅扩展,提升协作效率;FreeMarker则专注于打造一套强大的模板语言来提升逻辑表达效率。
在实际开发中,不必过分纠结于“孰优孰劣”。Spring Boot的自动配置机制已经极大地简化了集成过程。决策的关键应基于团队的技术背景与项目的具体需求。对于标准的 Java 管理后台项目,两者都能可靠地完成任务,选择你最熟悉或最符合项目风格的那个即可。