我们使用速度来解析我们的模板。
Velocity 开发人员指南建议为每个解析创建一个新的 VelocityContext
但是VelocityEngine
和RuntimeInstances
呢?
我们可以重用它们还是每次调用都创建新实例更好?VelocityEngine 的新实例会导致内存泄漏吗?
public String parse(String templateStr, Map<String, String> params) {
StringWriter writer = new StringWriter();
try {
VelocityEngine velocityEngine = new VelocityEngine();
velocityEngine.init();
RuntimeServices rs = RuntimeSingleton.getRuntimeServices();
StringReader sr = new StringReader(templateStr);
SimpleNode sn = rs.parse(sr, "template");
Template t = new Template();
t.setRuntimeServices(rs);
t.setData(sn);
t.initDocument();
VelocityContext context = new VelocityContext();
if (params != null && !params.isEmpty()) {
for (Entry<String, String> entry : params.entrySet()) {
context.put(entry.getKey(), entry.getValue());
}
}
t.merge(context, writer);
} catch (Exception e) {
LOGGER.error("Exception in velocity parsing", e);
}
return writer.toString();
}
Velocity 允许您使用单例模型
Velocity.setProperty(Velocity.RUNTIME_LOG_NAME, "mylog"); Velocity.init(); Template t = Velocity.getTemplate("foo.vm");
开发人员有两个使用 Velocity 引擎的选项:单例模型和单独的实例模型。两种方法使用相同的核心 Velocity 代码,提供这些代码是为了使 Velocity 更容易集成到您的 Java 应用程序中。
基本上,您可以使用Velocity类代替VelocityEngine:
此类提供了 Velocity 模板引擎的单独新实例。使用的替代模型是使用采用单例模型的速度类。
RuntimeInstance
是一个你不必处理的内部类。
VelocityEngine
以及单例类Velocity
(依赖于VelocityEngine
(是可重入的(以及它们关联的模板资源加载器(。这意味着它们可以安全地在多线程环境中使用。
每次实例化VelocityEngine
时,都需要调用init()
一次。 重用以前的VelocityEngine
实例可避免进行额外的init()
调用。
但是,重用VelocityEngine
实例的主要好处是通过其资源加载程序使用自动模板解析和缓存。 在问题的代码中,您手动实例化Template
对象并使用字符串中的数据加载它们。 一种更简洁的方法是将VelocityEngine
配置为支持"字符串资源加载程序",然后将包含模板正文的每个字符串存储在与VelocityEngine
实例关联的StringResourceRepository
中。 这一切都在Velocity 2.1的这个StackOverflow答案中得到了证明。
另外还有几点注意事项:
-
Velocity 将负责自动解析您的模板 上面的链接中显示的方法。 无需在
Template
上手动解析或调用initDocument()
。 -
通过这种方法,Velocity 将负责缓存您的模板(以解析形式( 如果已配置字符串资源加载程序(在 启用了缓存的
VelocityEngine
实例(。 -
以上两点将使您的代码更简单、更快捷。 您可以进一步简化代码:您可以调用
yourVelocityEngineInstance.mergeTemplate()
,而不是调用yourVelocityEngineInstance.getTemplate()
然后merge()
。 -
通过调用
yourRepo.putStringResource()
将模板添加到StringResourceRepository
时,您可以指定模板名称以及模板的正文。 如果没有明显的名称可以使用,您可以编写一个 MD5 哈希函数来快速生成模板正文的 MD5 哈希字符串,并将其用作唯一名称(从另一个 Velocity 用户那里得到了这个提示(。 如果模板正文发生更改,则会生成一个不同的名称。 有一个相应的removeStringResource()
方法可以从字符串资源存储库中删除模板。 -
一旦模板被放置在字符串资源存储库中,Velocity就可以按名称"神奇地"找到它。 您可以调用
yourVelocityEngineInstance.resourceExists("YourTemplateName")
以查看存储库中是否存在给定的模板。
我不知道实例化和初始化的性能成本VelocityEngine
,RuntimeInstance
或VelocityContext
。 在 Velocity 文档提供有关优化性能的更清晰的指导之前,您必须进行自己的性能测试才能找到答案。