带缓存的freemarker工具类

我们在实际工作中有很多场景需要DB等地方获取到一个FTL的代码片段并执行它,所有有了如下带缓存的实现方式

POM:

<dependency>
  <groupId>org.freemarker</groupId>
  <artifactId>freemarker</artifactId>
  <version>2.3.31</version>
</dependency>

JAVA:

import com.longge.ActivityError;
import freemarker.cache.StringTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateNotFoundException;
import freemarker.template.Version;
import lombok.extern.slf4j.Slf4j;

import java.io.StringWriter;
import java.util.Map;

/**
 * 主要是要对string类型的模板进行cache
 * @author yangzhilong
 * @date 2021年10月22日 16:05
 */
@Slf4j
public class FreemarkerUtils {
    private static final int MAX_LOAD_TEMPLATE_COUNT = 2;
    private static final Configuration CFG = new Configuration(new Version("2.3.31"));
    private static final StringTemplateLoader LOADER = new StringTemplateLoader();
    static {
        CFG.setTemplateLoader(LOADER);
        CFG.setDefaultEncoding("UTF-8");
        // 不需要热加载
        CFG.setAutoFlush(false);
        // 设置模板更新后的延迟时间,我们这边需要设置
        CFG.setTemplateUpdateDelayMilliseconds(0);
    }

    private FreemarkerUtils(){}

    /**
     * 执行ftl字符串模板的解析
     * @param ftlStr
     * @param param
     * @return
     */
    public static String process(String ftlStr, Map<String, ?> param) {
        Template t = getTemplate(ftlStr, 0);
        return doProcess(t, param);
    }

    /**
     * 获取模板
     * @param ftlStr
     * @param retryCount
     * @return
     */
    private static Template getTemplate(String ftlStr, int retryCount) {
        try {
            Template template = CFG.getTemplate(ftlStr);
            log.info("模板获取成功:{}", ftlStr);
            return template;
        } catch (Exception e) {
            // 模板未找到,则加载模板
            if (e instanceof TemplateNotFoundException && retryCount<MAX_LOAD_TEMPLATE_COUNT) {
                log.info("模板获取失败:{},尝试{}去加载", ftlStr, retryCount);
                LOADER.putTemplate(ftlStr, ftlStr);
                return getTemplate(ftlStr, retryCount+1);
            } else {
                throw ActivityError.FLOW_ENGINE_EXECUTE_ERROR.exception("模板解析异常");
            }
        }
    }

    /**
     * 执行模板解析
     * @param template
     * @param param
     * @return
     */
    private static String doProcess(Template template, Map<String, ?> param) {
        try(StringWriter sw = new StringWriter();) {
            template.process(param, sw);
            sw.flush();
            return sw.toString();
        } catch (Exception e) {
            throw ActivityError.FLOW_ENGINE_EXECUTE_ERROR.exception("模板解析异常");
        }
    }
}

 

posted @ 2016-11-24 11:49  自行车上的程序员  阅读(3032)  评论(0编辑  收藏  举报