带缓存的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("模板解析异常"); } } }