使用FreeMarker配置动态模板


FreeMarker动态模板

目录
  • FreeMarker动态模板
    • 前言
    • 准备工作
    • FreeMarker
    • 代码构建
      • 项目结构
      • 创建 Configuration 实例
      • 调用
      • 模板文件
      • 调用结果
    • Tips

前言

当我们开发功能时,不仅要考虑当前,也要考虑之后的迭代.
对于邮件正文内容,有时候需要配置HTML格式,所以选择了FreeMarker

准备工作

  • FreeMarker的依赖
        
            org.springframework.boot
            spring-boot-starter-freemarker
        
  • 其余Spring相关依赖
        
            org.projectlombok
            lombok
            true
        

        
            org.springframework.boot
            spring-boot-starter-web
        

FreeMarker

官方文档 http://freemarker.foofun.cn/
最简单的模板通常是普通的HTML文件,当然也可以用来写word,pdf之类
对于FreeMarker的模板语言,和动态sql有些相似

既然是动态模板,那么是要传入数据的
http://freemarker.foofun.cn/dgui_datamodel_types.html
常用的传参类型有List,Map,自定义对象 在上方的官方文档中你可以查看支持的全部类型

代码构建

项目结构

创建 Configuration 实例

参考官方文档中步骤 http://freemarker.foofun.cn/pgui_quickstart.html

package com.lizi.util;

import freemarker.template.Configuration;
import freemarker.template.Template;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;

import javax.annotation.PostConstruct;
import java.util.Locale;

/**
 * @author lizi
 * @description FreeMarkerUtil
 * @date 2022/01/01
 */
@Component
@Slf4j
public class FreeMarkerUtil {

    private static Configuration configuration = null;

    @PostConstruct
    public void init() {
        if (null == configuration) {
            // 设置版本号
            configuration = new Configuration(Configuration.VERSION_2_3_23);

            // ”/template“为模板文件来源
            configuration.setClassForTemplateLoading(FreeMarkerTemplateUtils.class, "/template");

            // 设置编码格式
            configuration.setEncoding(Locale.CHINA, "UTF-8");
        }
    }

    /**
     * @param file template文件路径
     * @param data 数据
     * @return String
     */
    public static String getResult(String file, Object data) {
        String result = "";
        try {
            // 获取通用模板
            Template template = configuration.getTemplate(file);

            // 通过模板创建动态数据
            result = FreeMarkerTemplateUtils.processTemplateIntoString(template, data);
        } catch (Exception e) {
            log.error("processTemplateIntoString error : {} ", e.getMessage());
        }
        return result;
    }
}

调用

package com.lizi.controller;

import com.lizi.Entity.Pokemon;
import com.lizi.util.FreeMarkerUtil;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * @author lizi
 * @description FreeMarkerController
 * @date 2022/01/01
 */
@RestController
public class FreeMarkerController {

    @PostMapping("/getTemplate")
    public String getTemplate() {

        // 创建数据模型
        Map dataMap = new HashMap<>(16);

        Map map = new HashMap<>(16);
        map.put("珍珠", "pearl");
        map.put("钻石", "diamond");

        Pokemon pokemon=new Pokemon();
        pokemon.setName("ground_dragon");
        pokemon.setRace("108,130,95,80,85,102");

        dataMap.put("strong",pokemon);
        dataMap.put("pokemon", map);
        dataMap.put("ground_dragon","108,130,95,80,85,102");
        return FreeMarkerUtil.getResult("template.ftl", dataMap);
    }
}


模板文件

对于模板语言,可以更多的去参考官方文档,


<#-- 传入类型是Map  ${ground_dragon} 表示对Map.get("ground_dragon") -->
${ground_dragon}
<#-- 我传入的类型是Map 这里pokemon 表示Map.get("pokemon")之后获取的value 代码中也是一个Map -->
<#if pokemon?exists>
<#--  list,表示遍历  -->
    <#list pokemon?keys as key>
        
            ${key}
            ${pokemon[key]}
        
    

<#-- Map.get("strong") 是一个自定义类 访问属性可以直接用.的方式获取 -->
${strong.name}
${strong.race}


调用结果


108,130,95,80,85,102
        
            钻石
            diamond
        
        
            珍珠
            pearl
        

ground_dragon
108,130,95,80,85,102


Tips

  1. 对于传入的数据模型,需要用Map做一层包装,不然会出错
  2. 如果对象可能不存在,需要做一层判断,不然会出错