!1202 增加jte模板引擎

* feat(jte): add jte: Java Template Engine
* feat(jte): add jte: Java Template Engine
* feat(jte): add jte: Java Template Engine
* feat(jte): add jte: Java Template Engine
This commit is contained in:
mymx2
2024-04-11 15:31:03 +00:00
committed by Looly
parent 26dcf5fd3d
commit 22b04c0ca7
8 changed files with 312 additions and 2 deletions

1
.gitignore vendored
View File

@@ -31,3 +31,4 @@ build/
# system ignore
.DS_Store
Thumbs.db
jte-classes/

View File

@@ -37,6 +37,7 @@
<freemarker.version>2.3.32</freemarker.version>
<enjoy.version>5.1.3</enjoy.version>
<thymeleaf.version>3.1.2.RELEASE</thymeleaf.version>
<jte.version>3.1.9</jte.version>
<mail.version>1.6.2</mail.version>
<jsch.version>0.1.55</jsch.version>
<sshj.version>0.38.0</sshj.version>
@@ -144,6 +145,13 @@
</exclusions>
<optional>true</optional>
</dependency>
<dependency>
<groupId>gg.jte</groupId>
<artifactId>jte</artifactId>
<version>${jte.version}</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.febit.wit</groupId>
<artifactId>wit-core</artifactId>

View File

@@ -0,0 +1,122 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* https://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.extra.template.engine.jte;
import gg.jte.CodeResolver;
import gg.jte.ContentType;
import gg.jte.resolve.DirectoryCodeResolver;
import gg.jte.resolve.ResourceCodeResolver;
import org.dromara.hutool.core.map.MapUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.extra.template.Template;
import org.dromara.hutool.extra.template.TemplateConfig;
import org.dromara.hutool.extra.template.engine.TemplateEngine;
import java.nio.file.Paths;
/**
* jte实现<br>
* 见:<a href="https://jte.gg/">https://jte.gg/</a>
*
* @author dy
*/
public class JteEngine implements TemplateEngine {
private TemplateConfig config = TemplateConfig.DEFAULT;
private gg.jte.TemplateEngine engine;
private final ContentType contentType = ContentType.Plain;
// --------------------------------------------------------------------------------- Constructor start
/**
* 默认构造
*/
public JteEngine() {
}
/**
* 构造
*
* @param config 模板配置
*/
public JteEngine(final TemplateConfig config) {
this.config = config;
createEngine();
}
/**
* 构造
*
* @param codeResolver {@link CodeResolver}
*/
public JteEngine(final CodeResolver codeResolver) {
createEngine(codeResolver, contentType);
}
// --------------------------------------------------------------------------------- Constructor end
@Override
public TemplateEngine init(TemplateConfig config) {
if (config != null) {
this.config = config;
}
createEngine();
return this;
}
@Override
public Template getTemplate(String resource) {
if (TemplateConfig.ResourceMode.STRING.equals(config.getResourceMode())) {
if (!StrUtil.endWithAny(config.getPath(), ".jte", ".kte")) {
throw new RuntimeException("路径path需以.jte/.kte结尾");
}
createEngine(new SimpleStringCodeResolver(MapUtil.of(config.getPath(), resource)), contentType);
return new JteTemplate(engine, config.getPath());
} else {
return new JteTemplate(engine, resource);
}
}
@Override
public gg.jte.TemplateEngine getRaw() {
return this.engine;
}
/**
* 创建引擎 {@link gg.jte.TemplateEngine }
*/
private void createEngine() {
switch (config.getResourceMode()) {
case CLASSPATH:
createEngine(new ResourceCodeResolver(config.getPath(), JteEngine.class.getClassLoader()), contentType);
break;
case FILE:
createEngine(new DirectoryCodeResolver(Paths.get(config.getPath())), contentType);
break;
case STRING:
// 这里无法直接创建引擎
break;
default:
break;
}
}
/**
* 创建引擎 {@link gg.jte.TemplateEngine }
*
* @param codeResolver CodeResolver
* @param contentType ContentType
*/
private void createEngine(CodeResolver codeResolver, ContentType contentType) {
this.engine = gg.jte.TemplateEngine.create(codeResolver, contentType);
}
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* https://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package org.dromara.hutool.extra.template.engine.jte;
import gg.jte.TemplateEngine;
import gg.jte.output.WriterOutput;
import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.io.file.FileUtil;
import org.dromara.hutool.extra.template.Template;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Map;
/**
* Jte模板实现
*
* @author dy
*/
public class JteTemplate implements Template, Serializable {
private static final long serialVersionUID = -2739915422007257186L;
private final TemplateEngine templateEngine;
private final String template;
public JteTemplate(TemplateEngine engine, String template) {
this.templateEngine = engine;
this.template = template;
}
@Override
public void render(Map<?, ?> bindingMap, Writer writer) {
templateEngine.render(template, bindingMap, new WriterOutput(writer));
}
@Override
public void render(Map<?, ?> bindingMap, OutputStream out) {
this.render(bindingMap, IoUtil.toWriter(out, StandardCharsets.UTF_8));
}
/**
* 将模板与绑定参数融合后输出到Writer
*
* @param model 实体类
* @param writer 输出
*/
public void render(Object model, Writer writer) {
templateEngine.render(template, model, new WriterOutput(writer));
}
/**
* 将模板与绑定参数融合后输出到流
*
* @param model 实体类
* @param out 输出
*/
public void render(Object model, OutputStream out) {
render(model, IoUtil.toWriter(out, StandardCharsets.UTF_8));
}
/**
* 写出到文件
*
* @param model 实体类
* @param file 输出到的文件
*/
public void render(final Object model, final File file) {
BufferedOutputStream out = null;
try {
out = FileUtil.getOutputStream(file);
this.render(model, out);
} finally {
IoUtil.closeQuietly(out);
}
}
/**
* 将模板与绑定参数融合后返回为字符串
*
* @param model 实体类
* @return 融合后的内容
*/
public String render(final Object model) {
final StringWriter writer = new StringWriter();
this.render(model, writer);
return writer.toString();
}
}

View File

@@ -0,0 +1,39 @@
package org.dromara.hutool.extra.template.engine.jte;
import gg.jte.CodeResolver;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* {@link CodeResolver} 字符串实现形式<br>
* 用于直接获取字符串模板
*
* @author cdy
* @since 6.0.0
*/
public class SimpleStringCodeResolver implements CodeResolver {
private final Map<String, String> templates;
public SimpleStringCodeResolver(Map<String, String> templates) {
this.templates = templates;
}
@Override
public String resolve(String name) {
return templates.get(name);
}
@Override
public long getLastModified(String name) {
return 0L;
}
@Override
public List<String> resolveAllTemplateNames() {
return new ArrayList<>(templates.keySet());
}
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright (c) 2023 looly(loolly@aliyun.com)
* Hutool is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* https://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
/**
* jte实现<br>
* 见:<a href="https://jte.gg/">https://jte.gg/</a>
*
* @author dy
*/
package org.dromara.hutool.extra.template.engine.jte;

View File

@@ -20,6 +20,7 @@ import org.dromara.hutool.extra.template.engine.TemplateEngineFactory;
import org.dromara.hutool.extra.template.engine.beetl.BeetlEngine;
import org.dromara.hutool.extra.template.engine.enjoy.EnjoyEngine;
import org.dromara.hutool.extra.template.engine.freemarker.FreemarkerEngine;
import org.dromara.hutool.extra.template.engine.jte.JteEngine;
import org.dromara.hutool.extra.template.engine.pebble.PebbleTemplateEngine;
import org.dromara.hutool.extra.template.engine.rythm.RythmEngine;
import org.dromara.hutool.extra.template.engine.thymeleaf.ThymeleafEngine;
@@ -30,8 +31,7 @@ import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
/**
* 模板引擎单元测试
@@ -158,6 +158,26 @@ public class TemplateFactoryTest {
Assertions.assertEquals("<h3>Hutool</h3>", result);
}
@Test
public void jteEngineTest() {
// 字符串模板
TemplateEngine engine = TemplateEngineFactory.createEngine(
new TemplateConfig("templates.jte").setCustomEngine(JteEngine.class));
Template template = engine.getTemplate("@param java.util.HashMap<String, String> map\n" +
"<h3>${map.get(\"message\")}</h3>");
Map<String, String> model = new HashMap<>();
model.put("message", "Hutool");
String result = template.render(model);
Assertions.assertEquals("<h3>Hutool</h3>", result);
//ClassPath模板
engine = TemplateEngineFactory.createEngine(
new TemplateConfig("templates", ResourceMode.CLASSPATH).setCustomEngine(JteEngine.class));
template = engine.getTemplate("jte_test.jte");
result = template.render(model);
Assertions.assertEquals("<h3>Hutool</h3>", result);
}
/**
* pebble template engine test
*/

View File

@@ -0,0 +1,2 @@
@param java.util.HashMap<String, String> map
<h3>${map.get("message")}</h3>