diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml index 986acdf7f..eb74276f9 100755 --- a/hutool-extra/pom.xml +++ b/hutool-extra/pom.xml @@ -151,6 +151,12 @@ 2.1.10 true + + io.pebbletemplates + pebble + 3.2.0 + true + diff --git a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/pebble/PebbleTemplate.java b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/pebble/PebbleTemplate.java new file mode 100644 index 000000000..12a3ebcfe --- /dev/null +++ b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/pebble/PebbleTemplate.java @@ -0,0 +1,65 @@ +package cn.hutool.extra.template.engine.pebble; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.reflect.TypeReference; +import cn.hutool.extra.template.Template; +import cn.hutool.extra.template.TemplateException; +import cn.hutool.extra.template.engine.velocity.VelocityTemplate; + +import java.io.*; +import java.util.Map; + +/** + * @author:zooooooooy + */ +public class PebbleTemplate implements Template { + + private final io.pebbletemplates.pebble.template.PebbleTemplate template; + + public PebbleTemplate(io.pebbletemplates.pebble.template.PebbleTemplate template) { + this.template = template; + } + + /** + * 包装pebbleTemplate模板 + * @param template + * @return + */ + public static PebbleTemplate wrap(final io.pebbletemplates.pebble.template.PebbleTemplate template) { + return (null == template) ? null : new PebbleTemplate(template); + } + + /** + * 渲染对象 + * @param bindingMap 绑定的参数,此Map中的参数会替换模板中的变量 + * @param writer 输出 + */ + @Override + public void render(Map bindingMap, Writer writer) { + + final Map map = Convert.convert(new TypeReference>() {}, bindingMap); + try { + this.template.evaluate(writer, map); + } catch (Exception e) { + throw new TemplateException("pebble template parse failed, cause by: ", e); + } + } + + /** + * 渲染对象 + * @param bindingMap 绑定的参数,此Map中的参数会替换模板中的变量 + * @param out 输出 + */ + @Override + public void render(Map bindingMap, OutputStream out) { + + final Map map = Convert.convert(new TypeReference>() {}, bindingMap); + try { + this.template.evaluate(new OutputStreamWriter(out), map); + } catch (Exception e) { + throw new TemplateException("pebble template parse failed, cause by: ", e); + } + + } + +} diff --git a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/pebble/PebbleTemplateEngine.java b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/pebble/PebbleTemplateEngine.java new file mode 100644 index 000000000..ea85109e2 --- /dev/null +++ b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/pebble/PebbleTemplateEngine.java @@ -0,0 +1,122 @@ +package cn.hutool.extra.template.engine.pebble; + +import cn.hutool.core.io.file.FileUtil; +import cn.hutool.core.text.StrUtil; +import cn.hutool.extra.template.Template; +import cn.hutool.extra.template.TemplateConfig; +import cn.hutool.extra.template.TemplateEngine; +import cn.hutool.extra.template.TemplateException; +import io.pebbletemplates.pebble.PebbleEngine; +import io.pebbletemplates.pebble.error.PebbleException; +import io.pebbletemplates.pebble.loader.ClasspathLoader; +import io.pebbletemplates.pebble.loader.FileLoader; +import io.pebbletemplates.pebble.loader.StringLoader; +import org.beetl.core.GroupTemplate; + +/** + * @author:zooooooooy + */ +public class PebbleTemplateEngine implements TemplateEngine { + + private PebbleEngine engine; + + public PebbleTemplateEngine() { + } + + public PebbleTemplateEngine(TemplateConfig config) { + init(config); + } + + @Override + public TemplateEngine init(TemplateConfig config) { + init(createEngine(config)); + return this; + } + + /** + * 初始化引擎 + * @param engine 引擎 + */ + private void init(PebbleEngine engine){ + this.engine = engine; + } + + /** + * 创建引擎 + * + * @param config 模板配置 + * @return {@link GroupTemplate} + */ + private static PebbleEngine createEngine(TemplateConfig config) { + if (null == config) { + config = TemplateConfig.DEFAULT; + } + + PebbleEngine pebbleEngine; + switch (config.getResourceMode()) { + case CLASSPATH: + ClasspathLoader classpathLoader = new ClasspathLoader(); + classpathLoader.setPrefix(StrUtil.addSuffixIfNot(config.getPath(), "/")); + pebbleEngine = new PebbleEngine.Builder() + .loader(classpathLoader) + .autoEscaping(false) + .build(); + break; + case FILE: + FileLoader fileLoader = new FileLoader(); + fileLoader.setPrefix(StrUtil.addSuffixIfNot(config.getPath(), "/")); + pebbleEngine = new PebbleEngine.Builder() + .loader(fileLoader) + .autoEscaping(false) + .build(); + break; + case WEB_ROOT: + fileLoader = new FileLoader(); + fileLoader.setPrefix(StrUtil.addSuffixIfNot(FileUtil.getAbsolutePath(FileUtil.file(FileUtil.getWebRoot(), config.getPath())), "/")); + pebbleEngine = new PebbleEngine.Builder() + .loader(fileLoader) + .autoEscaping(false) + .build(); + break; + case STRING: + StringLoader stringLoader = new StringLoader(); + stringLoader.setPrefix(StrUtil.addSuffixIfNot(config.getPath(), "/")); + pebbleEngine = new PebbleEngine.Builder() + .loader(stringLoader) + .autoEscaping(false) + .build(); + break; + default: + classpathLoader = new ClasspathLoader(); + classpathLoader.setPrefix(StrUtil.addSuffixIfNot(config.getPath(), "/")); + pebbleEngine = new PebbleEngine.Builder() + .loader(classpathLoader) + .autoEscaping(false) + .build(); + break; + } + + return pebbleEngine; + } + + /** + * 通过路径获取对应模板操作类 + * @param resource 资源,根据实现不同,此资源可以是模板本身,也可以是模板的相对路径 + * @return + */ + @Override + public Template getTemplate(String resource) { + + if (null == this.engine) { + init(TemplateConfig.DEFAULT); + } + + return PebbleTemplate.wrap(engine.getTemplate(resource)); + } + + @Override + public Object getRawEngine() { + return this.engine; + } + +} diff --git a/hutool-extra/src/main/java/cn/hutool/extra/template/engine/pebble/package-info.java b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/pebble/package-info.java new file mode 100644 index 000000000..5a4ad81bc --- /dev/null +++ b/hutool-extra/src/main/java/cn/hutool/extra/template/engine/pebble/package-info.java @@ -0,0 +1,6 @@ +/** + * pebble template实现,模板引擎介绍见:https://github.com/PebbleTemplates/pebble + * + * @author zooooooooy + */ +package cn.hutool.extra.template.engine.pebble; diff --git a/hutool-extra/src/test/java/cn/hutool/extra/template/TemplateUtilTest.java b/hutool-extra/src/test/java/cn/hutool/extra/template/TemplateUtilTest.java index 16fdf6ac7..bb6612ecc 100755 --- a/hutool-extra/src/test/java/cn/hutool/extra/template/TemplateUtilTest.java +++ b/hutool-extra/src/test/java/cn/hutool/extra/template/TemplateUtilTest.java @@ -6,6 +6,7 @@ import cn.hutool.extra.template.TemplateConfig.ResourceMode; import cn.hutool.extra.template.engine.beetl.BeetlEngine; import cn.hutool.extra.template.engine.enjoy.EnjoyEngine; import cn.hutool.extra.template.engine.freemarker.FreemarkerEngine; +import cn.hutool.extra.template.engine.pebble.PebbleTemplateEngine; import cn.hutool.extra.template.engine.rythm.RythmEngine; import cn.hutool.extra.template.engine.thymeleaf.ThymeleafEngine; import cn.hutool.extra.template.engine.velocity.VelocityEngine; @@ -143,6 +144,24 @@ public class TemplateUtilTest { Assert.assertEquals("

Hutool

", result); } + /** + * pebble template engine test + */ + @Test + public void pebbleEngineTest() { + // 字符串模板 + TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig("templates").setCustomEngine(PebbleTemplateEngine.class)); + Template template = engine.getTemplate("

{{ message }}

"); + String result = template.render(Dict.of().set("message", "Hutool")); + Assert.assertEquals("

Hutool

", result); + + //ClassPath模板 + engine = TemplateUtil.createEngine(new TemplateConfig("templates", ResourceMode.CLASSPATH).setCustomEngine(PebbleTemplateEngine.class)); + template = engine.getTemplate("pebble_test.peb"); + result = template.render(Dict.of().set("name", "Hutool")); + Assert.assertEquals("hello, Hutool", result); + } + @Test @Ignore public void renderToFileTest() { diff --git a/hutool-extra/src/test/resources/templates/pebble_test.peb b/hutool-extra/src/test/resources/templates/pebble_test.peb new file mode 100644 index 000000000..e68a6be88 --- /dev/null +++ b/hutool-extra/src/test/resources/templates/pebble_test.peb @@ -0,0 +1 @@ +hello, {{name}}