Freemarker案例

wen java案例 1

Freemarker实战案例精讲——模板引擎如何重塑你的动态页面开发

目录导读

  1. Freemarker是什么?为什么它依然是后端渲染的“常青树”?
  2. 案例环境搭建:Spring Boot + Freemarker 的极简配置
  3. 核心案例一:商品列表页——数据模型与模板的“第一次握手”
  4. 核心案例二:条件渲染与循环——动态输出不再“笨拙”
  5. 核心案例三:宏与自定义函数——告别重复代码的“终极武器”
  6. 核心案例四:异常处理与空值安全——让模板不再“崩溃”
  7. Freemarker 与 Thymeleaf、JSP 的横向对比
  8. 性能优化与常见坑位规避(SEO角度特别提醒)
  9. 高频问答(FAQ)——解决你90%的困惑

Freemarker是什么?为什么它依然是后端渲染的“常青树”?

Freemarker 是一款基于 Java 的模板引擎,它不依赖 Servlet 容器,却能完美嵌入 Spring MVC,它的核心理念是模板 + 数据模型 = 输出文本,与 JSP 相比,它强制实现了业务逻辑与视图的彻底分离;与前后端分离的 Vue/React 相比,它在 SEO 场景(如电商详情页、新闻门户)中有着无可替代的优势——搜索引擎爬虫直接读取到完整 HTML 内容

Freemarker案例

为什么至今仍有大量团队选择它?

  • 性能极高:预编译模板,缓存机制成熟,吞吐量优于 Thymeleaf。
  • 语法轻量${user.name}<#if><#list>,学习成本极低。
  • 非侵入式:不强制引入标签库,任何纯文本文件(HTML、XML、JS)都能作为模板。

案例环境搭建:Spring Boot + Freemarker 的极简配置

第一步:引入依赖(Maven 坐标)

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

第二步:application.yml 关键配置

spring:
  freemarker:
    template-loader-path: classpath:/templates/
    suffix: .ftl
    cache: true
    charset: UTF-8
    request-context-attribute: request

提示:将 cache 设置为 true(生产环境),开发时可临时关闭。

第三步:Controller 中返回视图

@Controller
public class PageController {
    @GetMapping("/product")
    public String product(Model model) {
        model.addAttribute("productName", "智能手表Pro");
        return "product";  // 对应 product.ftl
    }
}

核心案例一:商品列表页——数据模型与模板的“第一次握手”

场景:后端返回一个商品列表,前端需要展示名称、价格、库存。

Controller 代码

List<Product> products = Arrays.asList(
    new Product("iPhone 15", 6999, 120),
    new Product("华为Mate60", 6499, 0),
    new Product("小米14", 3999, 350)
);
model.addAttribute("products", products);

模板(product.ftl)

<!DOCTYPE html>
<html>
<head><title>商品列表</title></head>
<body>
<h1>热卖商品</h1>
<#list products as p>
    <div class="product-card">
        <span class="name">${p.name}</span>
        <span class="price">¥${p.price?string(",#.##")}</span>
        <#if p.stock > 0>
            <span class="stock ok">现货 ${p.stock} 件</span>
        <#else>
            <span class="stock bad">暂时缺货</span>
        </#if>
    </div>
</#list>
</body>
</html>

精髓<#list> 自动遍历集合,?string 是内置的数字格式化指令,避免出现 0 的尴尬,这里直接体现了“数据与视图的解耦”——后端只传纯数据,展示逻辑完全由模板控制。


核心案例二:条件渲染与循环——动态输出不再“笨拙”

进阶需求:当商品价格大于 5000 时,添加“高端”标签;当库存为 0 时,显示“立即预约”按钮。

模板改进

<#list products as p>
    <div class="item ${(p.price > 5000)?then('high-end', 'normal')}">
        <h3>${p.name}</h3>
        <#if p.stock == 0>
            <a href="/subscribe/${p.id}" class="btn">立即预约</a>
        <#elseif p.stock < 50>
            <span class="warn">仅剩 ${p.stock} 件</span>
        <#else>
            <span class="ok">库存充足</span>
        </#if>
    </div>
</#list>

深度解析

  • ${condition?then(a, b)} 是 Freemarker 1.0 版本以后的三目运算符,比硬编码 <#if> 更简洁。
  • (p.price > 5000)?string('high-end', 'normal') 这种内联方式,能大幅减少模板代码行数。

核心案例三:宏与自定义函数——告别重复代码的“终极武器”

痛点:多个页面都要展示用户头像、评分星星、格式化日期。

定义宏(macro.ftl)

<#macro starRating score max=5>
    <#local fullStars = score?int>
    <#local halfStar = (score - fullStars) >= 0.5>
    <#list 1..max as i>
        <#if i <= fullStars>★<#elseif halfStar && i == fullStars+1>☆<#else>☆</#if>
    </#list>
</#macro>

使用宏

<#import "macros.ftl" as m>
商品评分:<@m.starRating score=4.5 />

实际价值:在大型项目中,宏能将公共 UI 组件化,配合 <#assign><#global>,甚至可以模拟“前端组件化”,大大提升维护效率。


核心案例四:异常处理与空值安全——让模板不再“崩溃”

常见错误:后端返回 null 字段,直接 ${user.address} 会抛出 InvalidReferenceException

安全写法

<!-- 方式1:默认值 -->
${user.address!"暂无地址"}
<!-- 方式2:防空指针链 -->
${(user.address.city)!"未知城市"}
<!-- 方式3:存在性判断 -->
<#if user??>...<#else>未登录</#if>
<!-- 方式4:尝试捕获异常 -->
<#attempt>
    正常渲染内容
<#recover>
    兜底内容(比如记录日志)
</#attempt>

SEO 延伸:如果页面因异常导致 500,搜索引擎会降低抓取频次,所以在模板层兜底能极大提升站点的可用性和爬虫友好度。


Freemarker 与 Thymeleaf、JSP 的横向对比

维度 Freemarker Thymeleaf JSP
性能 高(预编译) 中(每次渲染解析) 低(依赖JSP容器)
学习曲线 简单 中等(依赖th:属性) 平坦(但代码易混入Java)
前端调试 需要安装插件 可用浏览器直接打开静态原型 必须启动容器
Spring Boot原生支持 ✅ 自动配置 ✅ 自动配置 不推荐
适用场景 高性能门户、Web2.0页面 小型CMS、原型快速开发 老项目维护

追求页面高并发SEO 内容直出,Freemarker 是更理性的选择。


性能优化与常见坑位规避(SEO角度特别提醒)

性能三板斧

  1. 开启模板缓存(生产环境)——spring.freemarker.cache=true
  2. 减少模板中过于复杂的逻辑——把计算放到 Java 层,模板只做展示。
  3. 使用 ?js_string?json_string 转义——防止 XSS 攻击,同时保证广告联盟/统计代码正常加载。

SEO 专属坑位

  • 不要使用 JS 渲染关键内容(h1、商品描述),否则百度爬虫抓不到。
  • 确保输出的 HTML 是静态化文本,不要在 <title> 中使用 <#assign> 动态拼接带有特殊字符的内容。
  • URL 规范化:在模板中对链接使用 ?html 转义,避免 & 等符号被错误解析。

高频问答(FAQ)——解决你90%的困惑

Q1:Freemarker 能直接访问 Spring MVC 的 ModelAndView 里的方法吗? A:不能,模板只能访问 getter 方法(属性),不能调用业务逻辑方法,你必须将结果预先放入 Model。

Q2:如何在 Freemarker 中遍历 Map?

<#list map?keys as key>
    ${key}: ${map[key]}
</#list>

Q3:Freemarker 支持继承布局吗? A:支持,通过 <#include><#macro> 组合实现,或者配合 spring.ftl 使用 @spring.bind

Q4:模板修改后为什么没生效? A:检查是否开启了缓存,在 application.yml 中临时设置 cache: false,并清理浏览器缓存。

Q5:Freemarker 能输出 JSON 吗? A:可以,使用 <#assign json = data?json_string> 输出到 <script> 标签,或直接返回 JSON 模板。


Freemarker 并非“过气技术”,它在性能与 SEO 之间的平衡至今无人能敌,掌握了上述案例,你不仅能处理 80% 的后端渲染需求,更能为网站带来更友好的搜索引擎收录,模板引擎拼的不是花哨,而是控场能力,愿你用这份功底,构建出既快又可被“读懂”的优质页面。

上一篇Velocity案例

下一篇Thymeleaf案例

抱歉,评论功能暂时关闭!