【发布时间】:2014-03-10 22:05:16
【问题描述】:
我正在处理一些 Java 代码,其中 Velocity 1.7 设置为通过 ClasspathResourceLoader 检索模板。下面是一个精简的代码示例。它来自在 Jetty 服务器上运行的 Tapestry Web 应用程序。
Java 类、模板和要包含的文件都在同一个文件夹“testpackage”中,因此在生成的 JAR 中它们都在同一个包“testpackage”中。
问题是如果模板包含一个
#include("MyInclude.vm")
指令,Velocity 找不到“MyInclude.vm”,并抛出 ResourceNotFoundException。
由于在 getTemplate 的参数中我必须在模板名称前面加上包名,我也尝试在模板内的#include 中做同样的事情:
#include("testpackage/MyInclude.vm")
但唯一的区别是,如果我从 Eclipse 运行 Web 应用程序,后者可以工作,而前者甚至不能从 Eclipse 运行。 如果我构建、部署 JAR 并从部署运行 Web 应用程序,两种语法都会失败并出现相同的 ResourceNotFoundException。
http://velocity.apache.org/engine/releases/velocity-1.7/user-guide.html#Include 的 Velocity 文档说:
"出于安全原因,要包含的文件只能在 TEMPLATE_ROOT"
这肯定是我的问题的原因,但我无法找到任何关于 TEMPLATE_ROOT 实际是什么的更多信息。
这听起来很像一个环境变量,但我不知道我应该将它设置为什么,因为我使用的是 ClasspathResourceLoader,并且要包含的文件不是位于文件夹中的实际文件,它是在包含模板和 Java 类的 JAR 中(并且都在同一个包中)。
我发现另一个问题Where should I put Velocity template files for a command line utility built with Maven? 中提到了 TEMPLATE_ROOT,但它与使用 FileResourceLoader 有关。我需要继续使用 ClasspathResourceLoader,并且我需要将所有文件都放在 JAR 中,而不是作为某个文件夹中的普通文件在 JAR 之外。
TestVelocity.java
package testpackage;
import java.io.StringWriter;
import java.util.Properties;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
public class TestVelocity
{
public static String getText()
{
String text = "";
Properties properties = new Properties();
properties.setProperty("resource.loader", "class");
properties.setProperty("class.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
VelocityEngine engine = new VelocityEngine();
VelocityContext context = new VelocityContext();
StringWriter writer = new StringWriter();
try
{
engine.init(properties);
// This works because the template doesn't contain any #include
Template template = engine.getTemplate("testpackage/TemplateWithoutInclude.vm");
// This causes ResourceNotFoundException: Unable to find resource 'TemplateWithInclude.vm'
// Template template = engine.getTemplate("testpackage/TemplateWithInclude.vm");
template.merge(context, writer);
text = writer.toString();
}
catch (Exception e)
{
e.printStackTrace();
}
return text;
}
}
TemplateWithoutInclude.vm
<!DOCTYPE html>
<html>
<head></head>
<body>
<p>Hello</p>
</body>
</html>
TemplateWithInclude.vm
<!DOCTYPE html>
<html>
<head></head>
<body>
#include("MyInclude.vm")
</body>
</html>
MyInclude.vm
<p>
Hello
</p>
【问题讨论】: