From 2674e5b13ecbaca515e2ab0c59e40e9eeb868847 Mon Sep 17 00:00:00 2001 From: yudongbin Date: Fri, 31 Mar 2023 11:10:33 +0800 Subject: [PATCH] =?UTF-8?q?hutool-extra=E6=A8=A1=E6=9D=BF=E5=BC=95?= =?UTF-8?q?=E6=93=8E=E5=A2=9E=E5=8A=A0pebble=E5=BC=95=E6=93=8E=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E3=80=82Pebble=E6=98=AF=E4=B8=80=E6=AC=BE=E5=8F=97Twi?= =?UTF-8?q?g=E5=90=AF=E5=8F=91=E7=9A=84Java=E6=A8=A1=E6=9D=BF=E5=BC=95?= =?UTF-8?q?=E6=93=8E=E3=80=82=E5=AE=83=E5=85=B7=E6=9C=89=E6=A8=A1=E6=9D=BF?= =?UTF-8?q?=E7=BB=A7=E6=89=BF=E5=92=8C=E6=98=93=E4=BA=8E=E9=98=85=E8=AF=BB?= =?UTF-8?q?=E7=9A=84=E8=AF=AD=E6=B3=95=EF=BC=8C=E5=86=85=E7=BD=AE=E6=9C=89?= =?UTF-8?q?=E5=AE=89=E5=85=A8=E7=9A=84autoescaping=EF=BC=8C=E5=B9=B6?= =?UTF-8?q?=E5=8C=85=E6=8B=AC=E5=AF=B9=E5=9B=BD=E9=99=85=E5=8C=96=E7=9A=84?= =?UTF-8?q?=E7=BB=BC=E5=90=88=E6=94=AF=E6=8C=81=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hutool-extra/pom.xml | 6 + .../engine/pebble/PebbleTemplate.java | 65 ++++++++++ .../engine/pebble/PebbleTemplateEngine.java | 122 ++++++++++++++++++ .../template/engine/pebble/package-info.java | 6 + .../extra/template/TemplateUtilTest.java | 19 +++ .../test/resources/templates/pebble_test.peb | 1 + 6 files changed, 219 insertions(+) create mode 100644 hutool-extra/src/main/java/cn/hutool/extra/template/engine/pebble/PebbleTemplate.java create mode 100644 hutool-extra/src/main/java/cn/hutool/extra/template/engine/pebble/PebbleTemplateEngine.java create mode 100644 hutool-extra/src/main/java/cn/hutool/extra/template/engine/pebble/package-info.java create mode 100644 hutool-extra/src/test/resources/templates/pebble_test.peb 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}}