Freemarker修仙指南:从模板小厮到页面渲染大能的终极奥义

各位在前后端分离与不分离之间反复横跳的道友们!今天要解锁的是上古模板引擎Freemarker!这货虽然年岁已高(诞生于2003年),但在某些需要服务端渲染的场景,依然是"真香"选择!准备好用模板语法召唤动态HTML了吗? ✨


一、筑基篇:初识Freemarker

1.1 法宝祭炼(添加依赖)

xml 复制代码
<!-- Spring Boot集成版 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

<!-- 原生使用版 -->
<dependency>
    <groupId>org.freemarker</groupId>
    <artifactId>freemarker</artifactId>
    <version>2.3.32</version>
</dependency>

1.2 基础配置(Spring Boot版)

yaml 复制代码
# application.yml
spring:
  freemarker:
    suffix: .ftl               # 模板文件后缀
    template-loader-path: classpath:/templates/ # 模板存放目录
    cache: false               # 开发时关闭缓存
    charset: UTF-8             # 必须设置编码!
    content-type: text/html

二、金丹篇:模板语法大全

2.1 变量输出(灵气外放)

html 复制代码
<!-- 普通变量 -->
<p>用户名:${username}</p>

<!-- 避免null值爆炸 -->
<p>余额:${balance!0}元</p>  <!-- 默认值语法 -->

<!-- 日期格式化 -->
<p>注册时间:${registerTime?string("yyyy-MM-dd HH:mm")}</p>

2.2 流程控制(御剑飞行)

html 复制代码
<#-- if判断 -->
<#if user.vip>
    <p class="gold">尊贵的VIP用户</p>
<#else>
    <p>普通用户</p>
</#if>

<#-- 遍历列表 -->
<ul>
<#list products as product>
    <li>${product.name} - ¥${product.price}</li>
</#list>
</ul>

2.3 宏定义(分身术)

html 复制代码
<#-- 定义宏 -->
<#macro userCard user>
    <div class="card">
        <h3>${user.name}</h3>
        <p>${user.bio!"这个人很懒,什么都没写"}</p>
    </div>
</#macro>

<#-- 使用宏 -->
<@userCard user=currentUser />

三、元婴篇:Spring Boot集成

3.1 Controller传参(灵力输送)

java 复制代码
@Controller
public class UserController {
    
    @GetMapping("/profile")
    public String profile(Model model) {
        model.addAttribute("username", "张无忌");
        model.addAttribute("registerTime", new Date());
        model.addAttribute("vip", true);
        return "user/profile"; // 对应templates/user/profile.ftl
    }
}

3.2 全局共享变量(宗门大阵)

java 复制代码
@Configuration
public class FreemarkerConfig {
    
    @Autowired
    private freemarker.template.Configuration configuration;

    @PostConstruct
    public void init() throws TemplateModelException {
        configuration.setSharedVariable("appName", "修仙论坛"); // 全局可用
        configuration.setSharedVariable("copyright", "2023");
    }
}

四、化神篇:高级技巧

4.1 自定义指令(独创神通)

java 复制代码
public class RoleDirective implements TemplateDirectiveModel {
    
    @Override
    public void execute(Environment env, Map params, 
                       TemplateModel[] loopVars,
                       TemplateDirectiveBody body) throws TemplateException {
        
        String role = params.get("role").toString();
        String currentRole = (String) env.getVariable("userRole");
        
        if (role.equals(currentRole)) {
            body.render(env.getOut()); // 符合条件才渲染内容
        }
    }
}

// 注册指令
configuration.setSharedVariable("hasRole", new RoleDirective());

模板中使用

html 复制代码
<@hasRole role="ADMIN">
    <button>删除用户</button>
</@hasRole>

4.2 类型处理(灵根转换)

java 复制代码
// 注册自定义日期格式化
configuration.setObjectWrapper(new DefaultObjectWrapperBuilder(Configuration.VERSION_2_3_32).build() {
    @Override
    public TemplateModel wrap(Object obj) throws TemplateModelException {
        if (obj instanceof LocalDateTime) {
            return new SimpleDate(((LocalDateTime) obj).atZone(ZoneId.systemDefault()).toInstant());
        }
        return super.wrap(obj);
    }
});

五、大乘篇:安全与性能

5.1 防XSS攻击(护体罡气)

html 复制代码
<#-- 默认输出会进行HTML转义 -->
<p>${userInput}</p> 

<#-- 禁用转义(慎用!) -->
<p>${userInput?no_esc}</p>

5.2 模板缓存优化(灵气循环)

java 复制代码
@Bean
public FreeMarkerConfigurationFactoryBean factoryBean() {
    FreeMarkerConfigurationFactoryBean bean = new FreeMarkerConfigurationFactoryBean();
    bean.setTemplateLoaderPath("classpath:/templates");
    bean.setPreferFileSystemAccess(false); // 禁用文件系统监听,提升性能
    bean.setDefaultEncoding("UTF-8");
    return bean;
}

六、实战心法

6.1 生成静态HTML(点石成金)

java 复制代码
public void generateStaticPage() throws Exception {
    Template template = configuration.getTemplate("article.ftl");
    Map<String, Object> data = new HashMap<>();
    data.put("title", "Freemarker使用指南");
    
    try (Writer out = new FileWriter("output.html")) {
        template.process(data, out);
    }
}

6.2 邮件模板应用(飞剑传书)

html 复制代码
<#-- email_template.ftl -->
<html>
<body>
    <h1>尊敬的${user.name}:</h1>
    <p>您的新密码是:<strong>${newPassword}</strong></p>
    <p>请及时<a href="${resetLink}">登录修改</a></p>
</body>
</html>

Java调用

java 复制代码
String htmlContent = FreeMarkerTemplateUtils.processTemplateIntoString(
    template, model);
emailService.sendHtmlEmail(to, subject, htmlContent);

飞升指南:最佳实践

  1. 模板管理 :合理使用<#include>拆分公共部分
  2. 逻辑精简:复杂计算应在Java代码中完成
  3. 版本控制:模板文件也应纳入Git管理
  4. 安全第一:永远不要信任模板中的用户输入
相关推荐
毕设源码-朱学姐5 小时前
【开题答辩全过程】以 基于JavaWeb的网上家具商城设计与实现为例,包含答辩的问题和答案
java
C雨后彩虹7 小时前
CAS与其他并发方案的对比及面试常见问题
java·面试·cas·同步·异步·
java1234_小锋8 小时前
Java高频面试题:SpringBoot为什么要禁止循环依赖?
java·开发语言·面试
2501_944525548 小时前
Flutter for OpenHarmony 个人理财管理App实战 - 账户详情页面
android·java·开发语言·前端·javascript·flutter
计算机学姐8 小时前
基于SpringBoot的电影点评交流平台【协同过滤推荐算法+数据可视化统计】
java·vue.js·spring boot·spring·信息可视化·echarts·推荐算法
Filotimo_8 小时前
Tomcat的概念
java·tomcat
索荣荣9 小时前
Java Session 全面指南:原理、应用与实践(含 Spring Boot 实战)
java·spring boot·后端
Amumu121389 小时前
Vue Router(二)
java·前端
念越10 小时前
数据结构:栈堆
java·开发语言·数据结构