fix template bug

This commit is contained in:
Looly 2020-03-10 00:51:16 +08:00
parent 30e73d4b5a
commit 0781be4e1c
14 changed files with 308 additions and 132 deletions

View File

@ -13,6 +13,7 @@
* 【core 】 修复DataUtil.parseLocalDateTime无时间部分报错问题issue#I1B18H@Gitee
* 【core 】 修复NetUtil.isUsableLocalPort()判断问题issue#765@Github
* 【poi 】 修复ExcelWriter写出多个sheet错误的问题issue#766@Github
* 【extra 】 修复模板引擎自定义配置失效问题issue#767@Github
-------------------------------------------------------------------------------------------------------------

View File

@ -21,7 +21,7 @@ public abstract class AtomicLoader<T> implements Loader<T>, Serializable {
private static final long serialVersionUID = 1L;
/** 被加载对象的引用 */
private final AtomicReference<T> reference = new AtomicReference<T>();
private final AtomicReference<T> reference = new AtomicReference<>();
/**
* 获取一个对象第一次调用此方法时初始化对象然后返回之后调用此方法直接返回原对象

View File

@ -1,6 +1,6 @@
package cn.hutool.core.lang.tree;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.parser.DefaultNodeParser;
import cn.hutool.core.lang.tree.parser.NodeParser;
@ -8,7 +8,7 @@ import java.util.List;
import java.util.stream.Collectors;
/**
* 树工具类 可参考 cn.hutool.core.lang.TreeTest
* 树工具类
*
* @author liangbaikai
*/
@ -16,6 +16,9 @@ public class TreeUtil {
/**
* 树构建
*
* @param list 源数据集合
* @return List
*/
public static List<Tree<Integer>> build(List<TreeNode<Integer>> list) {
return build(list, 0);
@ -23,13 +26,25 @@ public class TreeUtil {
/**
* 树构建
*
* @param <E> ID类型
* @param list 源数据集合
* @param parentId 最顶层父id值 一般为 0 之类
* @return List
*/
public static <T> List<Tree<T>> build(List<TreeNode<T>> list, T parentId) {
public static <E> List<Tree<E>> build(List<TreeNode<E>> list, E parentId) {
return build(list, parentId, TreeNodeConfig.DEFAULT_CONFIG, new DefaultNodeParser<>());
}
/**
* 树构建
*
* @param <T> 转换的实体 为数据源里的对象类型
* @param <E> ID类型
* @param list 源数据集合
* @param parentId 最顶层父id值 一般为 0 之类
* @param nodeParser 转换器
* @return List
*/
public static <T, E> List<Tree<E>> build(List<T> list, E parentId, NodeParser<T, E> nodeParser) {
return build(list, parentId, TreeNodeConfig.DEFAULT_CONFIG, nodeParser);
@ -38,22 +53,23 @@ public class TreeUtil {
/**
* 树构建
*
* @param <T> 转换的实体 为数据源里的对象类型
* @param <E> ID类型
* @param list 源数据集合
* @param parentId 最顶层父id值 一般为 0 之类
* @param treeNodeConfig 配置
* @param nodeParser 转换器
* @param <T> 转换的实体 为数据源里的对象类型
* @param nodeParser 转换器
* @return List
*/
public static <T, E> List<Tree<E>> build(List<T> list, E parentId, TreeNodeConfig treeNodeConfig, NodeParser<T, E> nodeParser) {
List<Tree<E>> treeNodes = CollectionUtil.newArrayList();
List<Tree<E>> treeNodes = CollUtil.newArrayList();
for (T obj : list) {
Tree<E> treeNode = new Tree<>(treeNodeConfig);
nodeParser.parse(obj, treeNode);
treeNodes.add(treeNode);
}
List<Tree<E>> finalTreeNodes = CollectionUtil.newArrayList();
List<Tree<E>> finalTreeNodes = CollUtil.newArrayList();
for (Tree<E> treeNode : treeNodes) {
if (parentId.equals(treeNode.getParentId())) {
finalTreeNodes.add(treeNode);
@ -75,7 +91,7 @@ public class TreeUtil {
*/
private static <T> void innerBuild(List<Tree<T>> treeNodes, Tree<T> parentNode, int deep, Integer maxDeep) {
if (CollectionUtil.isEmpty(treeNodes)) {
if (CollUtil.isEmpty(treeNodes)) {
return;
}
//maxDeep 可能为空
@ -89,7 +105,7 @@ public class TreeUtil {
if (parentNode.getId().equals(childNode.getParentId())) {
List<Tree<T>> children = parentNode.getChildren();
if (children == null) {
children = CollectionUtil.newArrayList();
children = CollUtil.newArrayList();
parentNode.setChildren(children);
}
children.add(childNode);

View File

@ -43,8 +43,8 @@ public class TreeTest {
TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
// 自定义属性名 都要默认值的
treeNodeConfig.setWeightKey("order");
treeNodeConfig.setDeep(3);
treeNodeConfig.setIdKey("rid");
treeNodeConfig.setDeep(3);
//转换器
List<Tree<String>> treeNodes = TreeUtil.build(nodeList, "0", treeNodeConfig,

View File

@ -2,45 +2,58 @@ package cn.hutool.extra.template;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.Objects;
import cn.hutool.core.util.CharsetUtil;
/**
* 模板配置
*
*
* @author looly
* @since 4.1.0
*/
public class TemplateConfig implements Serializable {
private static final long serialVersionUID = 2933113779920339523L;
/** 编码 */
public static final TemplateConfig DEFAULT = new TemplateConfig();
/**
* 编码
*/
private Charset charset;
/** 模板路径如果ClassPath或者WebRoot模式则表示相对路径 */
/**
* 模板路径如果ClassPath或者WebRoot模式则表示相对路径
*/
private String path;
/** 模板资源加载方式 */
/**
* 模板资源加载方式
*/
private ResourceMode resourceMode;
/**
* 自定义引擎当多个jar包引入时可以自定使用的默认引擎
*/
private Class<? extends TemplateEngine> customEngine;
/**
* 默认构造使用UTF8编码默认从ClassPath获取模板
*/
public TemplateConfig() {
this((String)null);
this(null);
}
/**
* 构造默认UTF-8编码
*
*
* @param path 模板路径如果ClassPath或者WebRoot模式则表示相对路径
*/
public TemplateConfig(String path) {
this(path, ResourceMode.STRING);
}
/**
* 构造默认UTF-8编码
*
* @param path 模板路径如果ClassPath或者WebRoot模式则表示相对路径
*
* @param path 模板路径如果ClassPath或者WebRoot模式则表示相对路径
* @param resourceMode 模板资源加载方式
*/
public TemplateConfig(String path, ResourceMode resourceMode) {
@ -49,9 +62,9 @@ public class TemplateConfig implements Serializable {
/**
* 构造
*
* @param charset 编码
* @param path 模板路径如果ClassPath或者WebRoot模式则表示相对路径
*
* @param charset 编码
* @param path 模板路径如果ClassPath或者WebRoot模式则表示相对路径
* @param resourceMode 模板资源加载方式
*/
public TemplateConfig(Charset charset, String path, ResourceMode resourceMode) {
@ -62,21 +75,21 @@ public class TemplateConfig implements Serializable {
/**
* 获取编码
*
*
* @return 编码
*/
public Charset getCharset() {
return charset;
}
/**
* 获取编码
*
*
* @return 编码
* @since 4.1.11
*/
public String getCharsetStr() {
if(null == this.charset) {
if (null == this.charset) {
return null;
}
return this.charset.toString();
@ -84,7 +97,7 @@ public class TemplateConfig implements Serializable {
/**
* 设置编码
*
*
* @param charset 编码
*/
public void setCharset(Charset charset) {
@ -93,7 +106,7 @@ public class TemplateConfig implements Serializable {
/**
* 获取模板路径如果ClassPath或者WebRoot模式则表示相对路径
*
*
* @return 模板路径
*/
public String getPath() {
@ -102,7 +115,7 @@ public class TemplateConfig implements Serializable {
/**
* 设置模板路径如果ClassPath或者WebRoot模式则表示相对路径
*
*
* @param path 模板路径
*/
public void setPath(String path) {
@ -111,7 +124,7 @@ public class TemplateConfig implements Serializable {
/**
* 获取模板资源加载方式
*
*
* @return 模板资源加载方式
*/
public ResourceMode getResourceMode() {
@ -120,67 +133,81 @@ public class TemplateConfig implements Serializable {
/**
* 设置模板资源加载方式
*
*
* @param resourceMode 模板资源加载方式
*/
public void setResourceMode(ResourceMode resourceMode) {
this.resourceMode = resourceMode;
}
/**
* 获取自定义引擎null表示系统自动判断
*
* @return 自定义引擎null表示系统自动判断
* @since 5.2.1
*/
public Class<? extends TemplateEngine> getCustomEngine() {
return customEngine;
}
/**
* 设置自定义引擎null表示系统自动判断
*
* @param customEngine 自定义引擎null表示系统自动判断
* @return this
* @since 5.2.1
*/
public TemplateConfig setCustomEngine(Class<? extends TemplateEngine> customEngine) {
this.customEngine = customEngine;
return this;
}
/**
* 资源加载方式枚举
*
*
* @author looly
*/
public enum ResourceMode {
/** 从ClassPath加载模板 */
/**
* 从ClassPath加载模板
*/
CLASSPATH,
/** 从File目录加载模板 */
/**
* 从File目录加载模板
*/
FILE,
/** 从WebRoot目录加载模板 */
/**
* 从WebRoot目录加载模板
*/
WEB_ROOT,
/** 从模板文本加载模板 */
/**
* 从模板文本加载模板
*/
STRING,
/** 复合加载模板分别从File、ClassPath、Web-root、String方式尝试查找模板 */
/**
* 复合加载模板分别从FileClassPathWeb-rootString方式尝试查找模板
*/
COMPOSITE
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((charset == null) ? 0 : charset.hashCode());
result = prime * result + ((path == null) ? 0 : path.hashCode());
result = prime * result + ((resourceMode == null) ? 0 : resourceMode.hashCode());
return result;
public boolean equals(Object o) {
if (this == o){
return true;
}
if (o == null || getClass() != o.getClass()){
return false;
}
TemplateConfig that = (TemplateConfig) o;
return Objects.equals(charset, that.charset) &&
Objects.equals(path, that.path) &&
resourceMode == that.resourceMode &&
Objects.equals(customEngine, that.customEngine);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
TemplateConfig other = (TemplateConfig) obj;
if (charset == null) {
if (other.charset != null) {
return false;
}
} else if (!charset.equals(other.charset)) {
return false;
}
if (path == null) {
if (other.path != null) {
return false;
}
} else if (!path.equals(other.path)) {
return false;
}
return resourceMode == other.resourceMode;
public int hashCode() {
return Objects.hash(charset, path, resourceMode, customEngine);
}
}

View File

@ -2,17 +2,25 @@ package cn.hutool.extra.template;
/**
* 引擎接口通过实现此接口从而使用对应的模板引擎
*
*
* @author looly
*/
public interface TemplateEngine {
/**
* 使用指定配置文件初始化模板引擎
*
* @param config 配置文件
* @return this
*/
TemplateEngine init(TemplateConfig config);
/**
* 获取模板
*
*
* @param resource 资源根据实现不同此资源可以是模板本身也可以是模板的相对路径
* @return 模板实现
*/
Template getTemplate(String resource);
}

View File

@ -1,5 +1,6 @@
package cn.hutool.extra.template.engine;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.ServiceLoaderUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.template.TemplateConfig;
@ -35,9 +36,15 @@ public class TemplateFactory {
* @return {@link Engine}
*/
private static TemplateEngine doCreate(TemplateConfig config) {
final TemplateEngine engine = ServiceLoaderUtil.loadFirstAvailable(TemplateEngine.class);
final Class<? extends TemplateEngine> customEngineClass = config.getCustomEngine();
final TemplateEngine engine;
if(null != customEngineClass){
engine = ReflectUtil.newInstance(customEngineClass);
}else{
engine = ServiceLoaderUtil.loadFirstAvailable(TemplateEngine.class);
}
if(null != engine){
return engine;
return engine.init(config);
}
throw new TemplateException("No template found ! Please add one of template jar to your project !");

View File

@ -23,15 +23,13 @@ import cn.hutool.extra.template.TemplateEngine;
*/
public class BeetlEngine implements TemplateEngine {
private final GroupTemplate engine;
private GroupTemplate engine;
// --------------------------------------------------------------------------------- Constructor start
/**
* 默认构造
*/
public BeetlEngine() {
this(new TemplateConfig());
}
public BeetlEngine() {}
/**
* 构造
@ -39,7 +37,7 @@ public class BeetlEngine implements TemplateEngine {
* @param config 模板配置
*/
public BeetlEngine(TemplateConfig config) {
this(createEngine(config));
init(config);
}
/**
@ -48,12 +46,30 @@ public class BeetlEngine implements TemplateEngine {
* @param engine {@link GroupTemplate}
*/
public BeetlEngine(GroupTemplate engine) {
this.engine = engine;
init(engine);
}
// --------------------------------------------------------------------------------- Constructor end
@Override
public TemplateEngine init(TemplateConfig config) {
init(createEngine(config));
return this;
}
/**
* 初始化引擎
* @param engine 引擎
*/
private void init(GroupTemplate engine){
this.engine = engine;
}
@Override
public Template getTemplate(String resource) {
if(null == this.engine){
init(TemplateConfig.DEFAULT);
}
return BeetlTemplate.wrap(engine.getTemplate(resource));
}
@ -65,7 +81,7 @@ public class BeetlEngine implements TemplateEngine {
*/
private static GroupTemplate createEngine(TemplateConfig config) {
if (null == config) {
config = new TemplateConfig();
config = TemplateConfig.DEFAULT;
}
switch (config.getResourceMode()) {

View File

@ -1,17 +1,14 @@
package cn.hutool.extra.template.engine.enjoy;
import org.beetl.core.GroupTemplate;
import com.jfinal.template.source.FileSourceFactory;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.template.Template;
import cn.hutool.extra.template.TemplateConfig;
import cn.hutool.extra.template.TemplateConfig.ResourceMode;
import cn.hutool.extra.template.TemplateEngine;
import com.jfinal.template.source.FileSourceFactory;
import org.beetl.core.GroupTemplate;
/**
* Enjoy库的引擎包装
@ -29,9 +26,7 @@ public class EnjoyEngine implements TemplateEngine {
/**
* 默认构造
*/
public EnjoyEngine() {
this(new TemplateConfig());
}
public EnjoyEngine() {}
/**
* 构造
@ -39,8 +34,7 @@ public class EnjoyEngine implements TemplateEngine {
* @param config 模板配置
*/
public EnjoyEngine(TemplateConfig config) {
this(createEngine(config));
this.resourceMode = config.getResourceMode();
init(config);
}
/**
@ -49,12 +43,33 @@ public class EnjoyEngine implements TemplateEngine {
* @param engine {@link com.jfinal.template.Engine}
*/
public EnjoyEngine(com.jfinal.template.Engine engine) {
this.engine = engine;
init(engine);
}
// --------------------------------------------------------------------------------- Constructor end
@Override
public TemplateEngine init(TemplateConfig config) {
if(null == config){
config = TemplateConfig.DEFAULT;
}
this.resourceMode = config.getResourceMode();
init(createEngine(config));
return this;
}
/**
* 初始化引擎
* @param engine 引擎
*/
private void init(com.jfinal.template.Engine engine){
this.engine = engine;
}
@Override
public Template getTemplate(String resource) {
if(null == this.engine){
init(TemplateConfig.DEFAULT);
}
if (ObjectUtil.equal(ResourceMode.STRING, this.resourceMode)) {
return EnjoyTemplate.wrap(this.engine.getTemplateByString(resource));
}
@ -68,7 +83,6 @@ public class EnjoyEngine implements TemplateEngine {
* @return {@link GroupTemplate}
*/
private static com.jfinal.template.Engine createEngine(TemplateConfig config) {
Assert.notNull(config, "Template config is null !");
final com.jfinal.template.Engine engine = com.jfinal.template.Engine.create("Hutool-Enjoy-Engine-" + IdUtil.fastSimpleUUID());
engine.setEncoding(config.getCharsetStr());

View File

@ -26,9 +26,7 @@ public class FreemarkerEngine implements TemplateEngine {
/**
* 默认构造
*/
public FreemarkerEngine() {
this(new TemplateConfig());
}
public FreemarkerEngine() {}
/**
* 构造
@ -36,7 +34,7 @@ public class FreemarkerEngine implements TemplateEngine {
* @param config 模板配置
*/
public FreemarkerEngine(TemplateConfig config) {
this(createCfg(config));
init(config);
}
/**
@ -45,12 +43,32 @@ public class FreemarkerEngine implements TemplateEngine {
* @param freemarkerCfg {@link Configuration}
*/
public FreemarkerEngine(Configuration freemarkerCfg) {
this.cfg = freemarkerCfg;
init(freemarkerCfg);
}
// --------------------------------------------------------------------------------- Constructor end
@Override
public TemplateEngine init(TemplateConfig config) {
if(null == config){
config = TemplateConfig.DEFAULT;
}
init(createCfg(config));
return this;
}
/**
* 初始化引擎
* @param freemarkerCfg Configuration
*/
private void init(Configuration freemarkerCfg){
this.cfg = freemarkerCfg;
}
@Override
public Template getTemplate(String resource) {
if(null == this.cfg){
init(TemplateConfig.DEFAULT);
}
try {
return FreemarkerTemplate.wrap(this.cfg.getTemplate(resource));
} catch(IOException e) {

View File

@ -21,9 +21,7 @@ public class RythmEngine implements TemplateEngine {
/**
* 默认构造
*/
public RythmEngine() {
this(new TemplateConfig());
}
public RythmEngine() {}
/**
* 构造
@ -31,7 +29,7 @@ public class RythmEngine implements TemplateEngine {
* @param config 模板配置
*/
public RythmEngine(TemplateConfig config) {
this(createEngine(config));
init(config);
}
/**
@ -40,13 +38,33 @@ public class RythmEngine implements TemplateEngine {
* @param engine {@link org.rythmengine.RythmEngine}
*/
public RythmEngine(org.rythmengine.RythmEngine engine) {
this.engine = engine;
init(engine);
}
// --------------------------------------------------------------------------------- Constructor end
@Override
public TemplateEngine init(TemplateConfig config) {
if(null == config){
config = TemplateConfig.DEFAULT;
}
init(createEngine(config));
return this;
}
/**
* 初始化引擎
* @param engine 引擎
*/
private void init(org.rythmengine.RythmEngine engine){
this.engine = engine;
}
@Override
public Template getTemplate(String resource) {
return RythmTemplate.wrap(engine.getTemplate(resource));
if(null == this.engine){
init(TemplateConfig.DEFAULT);
}
return RythmTemplate.wrap(this.engine.getTemplate(resource));
}
/**

View File

@ -28,9 +28,7 @@ public class ThymeleafEngine implements TemplateEngine {
/**
* 默认构造
*/
public ThymeleafEngine() {
this(new TemplateConfig());
}
public ThymeleafEngine() {}
/**
* 构造
@ -38,8 +36,7 @@ public class ThymeleafEngine implements TemplateEngine {
* @param config 模板配置
*/
public ThymeleafEngine(TemplateConfig config) {
this(createEngine(config));
this.config = config;
init(config);
}
/**
@ -48,12 +45,33 @@ public class ThymeleafEngine implements TemplateEngine {
* @param engine {@link org.thymeleaf.TemplateEngine}
*/
public ThymeleafEngine(org.thymeleaf.TemplateEngine engine) {
this.engine = engine;
init(engine);
}
// --------------------------------------------------------------------------------- Constructor end
@Override
public TemplateEngine init(TemplateConfig config) {
if(null == config){
config = TemplateConfig.DEFAULT;
}
this.config = config;
init(createEngine(config));
return this;
}
/**
* 初始化引擎
* @param engine 引擎
*/
private void init(org.thymeleaf.TemplateEngine engine){
this.engine = engine;
}
@Override
public Template getTemplate(String resource) {
if(null == this.engine){
init(TemplateConfig.DEFAULT);
}
return ThymeleafTemplate.wrap(this.engine, resource, (null == this.config) ? null : this.config.getCharset());
}

View File

@ -21,9 +21,7 @@ public class VelocityEngine implements TemplateEngine {
/**
* 默认构造
*/
public VelocityEngine() {
this(new TemplateConfig());
}
public VelocityEngine() {}
/**
* 构造
@ -31,7 +29,7 @@ public class VelocityEngine implements TemplateEngine {
* @param config 模板配置
*/
public VelocityEngine(TemplateConfig config) {
this(createEngine(config));
init(config);
}
/**
@ -40,10 +38,27 @@ public class VelocityEngine implements TemplateEngine {
* @param engine {@link org.apache.velocity.app.VelocityEngine}
*/
public VelocityEngine(org.apache.velocity.app.VelocityEngine engine) {
this.engine = engine;
init(engine);
}
// --------------------------------------------------------------------------------- Constructor end
@Override
public TemplateEngine init(TemplateConfig config) {
if(null == config){
config = TemplateConfig.DEFAULT;
}
init(createEngine(config));
return this;
}
/**
* 初始化引擎
* @param engine 引擎
*/
private void init(org.apache.velocity.app.VelocityEngine engine){
this.engine = engine;
}
/**
* 获取原始的引擎对象
*
@ -56,6 +71,9 @@ public class VelocityEngine implements TemplateEngine {
@Override
public Template getTemplate(String resource) {
if(null == this.engine){
init(TemplateConfig.DEFAULT);
}
return VelocityTemplate.wrap(engine.getTemplate(resource));
}

View File

@ -27,11 +27,17 @@ public class TemplateUtilTest {
@Test
public void createEngineTest() {
// 默认模板引擎此处为Beetl
// 字符串模板, 默认模板引擎此处为Beetl
TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig());
Template template = engine.getTemplate("hello,${name}");
String result = template.render(Dict.create().set("name", "hutool"));
Assert.assertEquals("hello,hutool", result);
// classpath中获取模板
engine = TemplateUtil.createEngine(new TemplateConfig("templates", ResourceMode.CLASSPATH));
Template template2 = engine.getTemplate("beetl_test.btl");
String result2 = template2.render(Dict.create().set("name", "hutool"));
Assert.assertEquals("hello,hutool", result2);
}
@Test
@ -52,7 +58,8 @@ public class TemplateUtilTest {
@Test
public void rythmEngineTest() {
// 字符串模板
TemplateEngine engine = new RythmEngine(new TemplateConfig("templates"));
TemplateEngine engine = TemplateUtil.createEngine(
new TemplateConfig("templates").setCustomEngine(RythmEngine.class));
Template template = engine.getTemplate("hello,@name");
String result = template.render(Dict.create().set("name", "hutool"));
Assert.assertEquals("hello,hutool", result);
@ -66,13 +73,15 @@ public class TemplateUtilTest {
@Test
public void freemarkerEngineTest() {
// 字符串模板
TemplateEngine engine = new FreemarkerEngine(new TemplateConfig("templates", ResourceMode.STRING));
TemplateEngine engine = TemplateUtil.createEngine(
new TemplateConfig("templates", ResourceMode.STRING).setCustomEngine(FreemarkerEngine.class));
Template template = engine.getTemplate("hello,${name}");
String result = template.render(Dict.create().set("name", "hutool"));
Assert.assertEquals("hello,hutool", result);
//ClassPath模板
engine = new FreemarkerEngine(new TemplateConfig("templates", ResourceMode.CLASSPATH));
engine = TemplateUtil.createEngine(
new TemplateConfig("templates", ResourceMode.CLASSPATH).setCustomEngine(FreemarkerEngine.class));
template = engine.getTemplate("freemarker_test.ftl");
result = template.render(Dict.create().set("name", "hutool"));
Assert.assertEquals("hello,hutool", result);
@ -81,13 +90,15 @@ public class TemplateUtilTest {
@Test
public void velocityEngineTest() {
// 字符串模板
TemplateEngine engine = new VelocityEngine(new TemplateConfig("templates", ResourceMode.STRING));
TemplateEngine engine = TemplateUtil.createEngine(
new TemplateConfig("templates", ResourceMode.STRING).setCustomEngine(VelocityEngine.class));
Template template = engine.getTemplate("你好,$name");
String result = template.render(Dict.create().set("name", "hutool"));
Assert.assertEquals("你好,hutool", result);
//ClassPath模板
engine = new VelocityEngine(new TemplateConfig("templates", ResourceMode.CLASSPATH));
engine = TemplateUtil.createEngine(
new TemplateConfig("templates", ResourceMode.CLASSPATH).setCustomEngine(VelocityEngine.class));
template = engine.getTemplate("templates/velocity_test.vtl");
result = template.render(Dict.create().set("name", "hutool"));
Assert.assertEquals("你好,hutool", result);
@ -97,13 +108,15 @@ public class TemplateUtilTest {
@Test
public void enjoyEngineTest() {
// 字符串模板
TemplateEngine engine = new EnjoyEngine(new TemplateConfig("templates"));
TemplateEngine engine = TemplateUtil.createEngine(
new TemplateConfig("templates").setCustomEngine(EnjoyEngine.class));
Template template = engine.getTemplate("#(x + 123)");
String result = template.render(Dict.create().set("x", 1));
Assert.assertEquals("124", result);
//ClassPath模板
engine = new EnjoyEngine(new TemplateConfig("templates", ResourceMode.CLASSPATH));
engine = new EnjoyEngine(
new TemplateConfig("templates", ResourceMode.CLASSPATH).setCustomEngine(EnjoyEngine.class));
template = engine.getTemplate("enjoy_test.etl");
result = template.render(Dict.create().set("x", 1));
Assert.assertEquals("124", result);
@ -112,13 +125,15 @@ public class TemplateUtilTest {
@Test
public void thymeleafEngineTest() {
// 字符串模板
TemplateEngine engine = new ThymeleafEngine(new TemplateConfig("templates"));
TemplateEngine engine = TemplateUtil.createEngine(
new TemplateConfig("templates").setCustomEngine(ThymeleafEngine.class));
Template template = engine.getTemplate("<h3 th:text=\"${message}\"></h3>");
String result = template.render(Dict.create().set("message", "Hutool"));
Assert.assertEquals("<h3>Hutool</h3>", result);
//ClassPath模板
engine = new ThymeleafEngine(new TemplateConfig("templates", ResourceMode.CLASSPATH));
engine = TemplateUtil.createEngine(
new TemplateConfig("templates", ResourceMode.CLASSPATH).setCustomEngine(ThymeleafEngine.class));
template = engine.getTemplate("thymeleaf_test.ttl");
result = template.render(Dict.create().set("message", "Hutool"));
Assert.assertEquals("<h3>Hutool</h3>", result);