Freemarker是一款历史悠久的Java模板引擎,其核心设计理念是将业务逻辑与视图展示彻底分离。它通过加载模板文件,将数据模型注入其中,最终生成动态文本输出。这种机制不仅适用于Web页面的HTML渲染,还能用于邮件模板生成、代码自动生成、配置文件拼接等多种场景。在Spring Boot框架中,整合Freemarker的过程被简化到了极致,开发者只需引入一个starter依赖,配合少量配置即可搭建起完整的模板渲染体系。

一、Freemarker核心概念与项目依赖准备
要理解Freemarker的工作机制,需要先弄清三个基本概念:模板、数据模型和输出。模板是一份包含静态文本和动态占位符的文件,通常以.ftl为扩展名。数据模型是一个树状结构的数据集合,由Java程序在运行时构建并提供给模板引擎。输出则是模板与数据模型合并后的最终结果,可以是HTML、XML、纯文本等任意格式。Freemarker本身不关心输出格式,它只负责按照模板规则把数据填入对应位置。
在Spring Boot项目中引入Freemarker非常简单。打开项目的pom.xml文件,在dependencies节点下添加spring-boot-starter-freemarker依赖即可。这个starter会自动引入Freemarker核心库以及Spring MVC对Freemarker的集成支持,无需额外配置版本号,Spring Boot的依赖管理机制会自动处理版本兼容问题。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>除了Maven依赖,项目目录结构也需要提前规划好。Spring Boot默认会从classpath下的templates目录加载Freemarker模板文件,因此需要在src/main/resources目录下创建一个名为templates的文件夹,所有.ftl文件都放在这个目录中。如果模板文件较多,可以在templates下按业务模块再划分子目录,引用时通过斜杠路径访问即可。
二、核心配置参数与Controller实现
Spring Boot为Freemarker提供了一系列可配置参数,全部通过application.properties或application.yml文件进行设置。其中几个关键参数需要特别关注。spring.freemarker.template-loader-path用于指定模板加载路径,默认值是classpath:/templates/,一般情况下保持默认即可。spring.freemarker.suffix指定模板文件后缀,默认值为.ftl。spring.freemarker.charset控制模板文件编码,建议设置为UTF-8以避免中文乱码问题。spring.freemarker.cache决定是否开启模板缓存,开发环境下建议关闭以便实时查看模板修改效果,生产环境则应开启以提升性能。
# 模板文件加载路径 spring.freemarker.template-loader-path=classpath:/templates/ # 模板文件后缀 spring.freemarker.suffix=.ftl # 模板编码 spring.freemarker.charset=UTF-8 # 开发环境关闭缓存 spring.freemarker.cache=false # 开启请求属性暴露 spring.freemarker.expose-request-attributes=true # 开启Session属性暴露 spring.freemarker.expose-session-attributes=true
配置完成后,接下来编写Controller层代码。Controller的作用是处理业务逻辑、组装数据模型,然后将数据传递给Freemarker模板进行渲染。在Spring MVC中,只需在Controller方法中返回一个字符串作为视图名称,同时通过Model或ModelMap对象把数据放入模型中,Spring Boot就会自动调用Freemarker视图解析器完成渲染。这种方式与传统的JSP开发模式非常相似,学习成本很低。
@Controller
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/user/list")
public String userList(Model model) {
// 查询用户列表
List<User> users = userService.findAllUsers();
// 将数据放入模型
model.addAttribute("users", users);
model.addAttribute("title", "用户管理列表");
// 返回视图名称,实际解析为 templates/user/list.ftl
return "user/list";
}
@GetMapping("/user/detail/{id}")
public String userDetail(@PathVariable Long id, Model model) {
User user = userService.findById(id);
model.addAttribute("user", user);
return "user/detail";
}
}上述代码中,Controller方法返回的字符串如user/list会被视图解析器拼接成完整的模板路径templates/user/list.ftl。Model对象中放入的数据在模板中可以直接通过属性名访问,比如model.addAttribute方法放入的数据,在模板中通过美元符号加变量名即可获取。这种数据传递方式是Spring MVC与Freemarker集成的核心机制,理解这一点对后续模板编写至关重要。
三、Freemarker模板语法详解与实战示例
Freemarker模板语法丰富且表达能力强,掌握常用语法是高效开发的基础。变量输出使用美元符号加花括号的形式,这是最基础的语法。当变量为对象时,可以通过点号访问其属性,例如访问user对象的name属性。如果变量为null,Freemarker会抛出异常,因此建议使用感叹号提供默认值,当变量为空时输出默认内容,避免程序报错中断。
条件判断使用if指令,语法格式为<#if condition>...<#else>...</#if>。循环遍历使用list指令,语法格式为<#list items as item>...</#list>。这两个指令在实际开发中使用频率极高,几乎每个模板都会用到。下面通过一个完整的用户列表页面模板来演示这些语法的综合运用。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>${title}</title>
</head>
<body>
<h1>${title}</h1>
<table border="1">
<tr>
<th>编号</th>
<th>用户名</th>
<th>邮箱</th>
<th>状态</th>
</tr>
<#list users as user>
<tr>
<td>${user.id}</td>
<td>${user.username!''}</td>
<td>${user.email!''}</td>
<td>
<#if user.active>
<span style="color:green">启用</span>
<#else>
<span style="color:red">禁用</span>
</#if>
</td>
</tr>
</#list>
</table>
</body>
</html>除了基本的变量输出、条件判断和循环遍历,Freemarker还提供了宏定义、函数调用、内建函数等高级特性。宏定义类似于其他语言中的函数,可以将重复使用的模板片段封装起来复用。内建函数则提供了丰富的数据处理能力,比如格式化日期、将字符串转为大写、获取集合长度等。这些内建函数以问号开头调用,能够大幅减少模板中的逻辑代码量,让模板更加简洁易读。
四、常见问题排查与性能优化建议
在Spring Boot整合Freemarker的实际开发中,开发者经常会遇到一些典型问题。最常见的是模板路径找不到的异常,报错信息通常为TemplateNotFoundException。出现这个问题时,首先检查模板文件是否放在了classpath:/templates/目录下,其次确认Controller返回的视图名称与模板文件路径是否匹配。如果模板放在子目录中,返回的视图名称必须包含完整相对路径,比如user/list对应templates/user/list.ftl文件。
另一个高频问题是中文乱码。乱码可能出现在两个环节:一是模板文件本身的编码问题,二是HTTP响应的编码问题。解决方法是在配置文件中设置spring.freemarker.charset为UTF-8,同时确保模板文件以UTF-8编码保存。如果是从数据库读取的数据出现乱码,还需要检查数据库连接字符串中的编码参数,确保数据库层面也是UTF-8编码。在模板的HTML头部,务必添加<meta charset="UTF-8">声明,让浏览器以正确编码解析页面内容。
性能优化方面,模板缓存是首要关注点。Freemarker在解析模板时会将其编译为Java类,这个过程有一定开销。开启缓存后,模板只会解析一次并缓存编译结果,后续请求直接使用缓存对象,能显著提升响应速度。在生产环境中,务必将spring.freemarker.cache设置为true。此外,模板中应避免编写过于复杂的业务逻辑,Freemarker的设计初衷是视图层展示工具,把复杂计算放在Java代码中完成,模板只负责简单的数据展示和条件判断,这样既保证可维护性,也有利于渲染性能。
对于需要生成非HTML内容的场景,比如邮件模板或PDF导出,可以通过FreeMarkerTemplateUtils工具类手动调用模板渲染。这种方式不依赖Spring MVC的视图解析机制,更加灵活。具体做法是注入Configuration对象,调用getTemplate方法获取模板对象,再调用process方法传入数据模型即可获得渲染后的字符串内容。这种方式在批量发送邮件、生成报表等后台任务中非常实用,能够充分发挥Freemarker的模板渲染能力。
Spring BootFreemarker模板引擎修改时间:2026-08-30 23:33:17