近期需要集成多个模板引擎,其中就包括handlebars,笔者根据热度,选择了开源的https://github.com/jknack/handlebars.java 作为依赖,但无奈却无法编译如下代码
Handlebars handlebars = new Handlebars();
Template template = handlebars.compileInline("Hello {{测试}}!");
大致翻看了git上的issue,以及部分源码,发现确实有此问题,似乎该库也以及久未维护。时间有限,也不能详细调试源码,所以就打算,使用java调用js引擎(js可编译中文)来完成。直接上代码
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import com.alibaba.fastjson.JSON;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.io.File;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.concurrent.ThreadPoolExecutor;
/**
* @author xiatiao
* @description handlebars js模板实现
* @date 2022/9/5
*/
@Component
public class HandlebarsTemplateJSConvert implements TemplateConvert {
//脚本引擎
private static ScriptEngine scriptEngine;
//js引擎是否加载
private volatile boolean engineLoaded = false;
//对象锁
Object lock = new Object();
@Resource
ThreadPoolExecutor threadPoolExecutor;
@PostConstruct
public void init() {
//忽略告警
System.setProperty("nashorn.args", "--no-deprecation-warning");
//不阻塞主线程-加载脚本
Thread thread = new Thread(() -> {
try {
//js引擎
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
scriptEngine = scriptEngineManager.getEngineByName("javascript");
InputStream inputStream = HandlebarsTemplateJSConvert.class.getResourceAsStream("/handlebars.js");
String jsContent = IoUtil.read(inputStream, StandardCharsets.UTF_8);
InputStream helperInputStream = HandlebarsTemplateJSConvert.class.getResourceAsStream("/helpers-handlebars.js");
String helperContent = IoUtil.read(helperInputStream, StandardCharsets.UTF_8);
scriptEngine.eval(jsContent);
scriptEngine.eval(helperContent);
engineLoaded = true;
synchronized (lock) {
//激活等待线程
lock.notifyAll();
}
} catch (ScriptException e) {
throw new RuntimeException("加载handlebars脚本引擎异常", e);
}
});
threadPoolExecutor.execute(thread);
}
@Override
public void convert(String templateDir, String templateFileName, String targetDir, String outFileName, Map param) throws Throwable {
String templateStr = FileUtil.readUtf8String(templateDir + File.separator + templateFileName);
String resultString = jsConvert(templateStr, param);
FileUtil.writeString(resultString, targetDir + File.separator + outFileName, StandardCharsets.UTF_8);
}
private String jsConvert(String template, Map param) throws Throwable {
//引擎加载结束以前线程等待
if (!engineLoaded) {
try {
synchronized (lock) {
lock.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
String jsonParam = JSON.toJSONString(param);
// 执行函数名
String functionName = "loadMe";
Invocable invocable = (Invocable) scriptEngine;
//Object eval = scriptEngine.eval("loadMe("{{a}}",{a:1})");
Object result = invocable.invokeFunction(functionName, template, jsonParam);
return result.toString();
}
}
/**
* 模板接口
* @author xiatiao
* @date 2022/9/5
*/
public interface TemplateConvert {
/**
* @description
* @param templateDir 模板目录
* @param templateFileName 模板文件名称
* @param targetDir 输出目录
* @param outFileName 输出文件名称
* @param param 参数
* @author xiatiao
* @date 2022/9/5
*/
void convert(String templateDir, String templateFileName,String targetDir ,String outFileName, Map param) throws Throwable;
}
笔者这里要实现多种模板,所以抽象了一个接口,规范接口的调用方式。
文中使用的handlebars.js, 下载地址:https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.js
helpers-handlebars.js文件内容如下:
function loadMe(templateStr,jsonStr){
var jsonObject = JSON.parse(jsonStr);
var template = Handlebars.compile(templateStr);
var result = template(jsonObject);
return result;
}
文件都保存到resources目录下即可。
本文由 转啊转 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为:
2022/09/26 23:24