当前位置: 首页 > 面试题库 >

如何使用ClasspathResourceLoader从Velocity模板中包含文件

韦睿
2023-03-14
问题内容

我正在处理一些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,并且要包含的文件不是文件夹中的实际文件,因此它位于JAR内包含模板和Java类(并且都在同一包中)。

我发现在另一个问题中提到了TEMPLATE_ROOT,对于使用Maven构建的命令行实用程序,应该将Velocity模板文件放在哪里?,但与使用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>

问题答案:

返回示例代码,可通过在Properties用于初始化引擎的实例中添加更多属性来解决该问题:

properties.setProperty(RuntimeConstants.EVENTHANDLER_INCLUDE, IncludeRelativePath.class.getName());

这允许引用要包含的文件的路径,作为相对于包含模板所在文件夹的路径。因此,如果两个文件都在同一文件夹中,则无需在#include指令中指定路径:just
#include("MyInclude.vm")

我也希望(对我)了解一些晦涩难懂的东西(例如对我来说)TEMPLATE_ROOT。是什么,因为我很难在任何地方找到记录的信息。但是无论如何,至少在我看来,它对应于Java项目的根软件包(“默认”软件包)。这意味着如果我不使用上面提到的其他属性,则将文件MyInclude.vm放在根包中即可。



 类似资料:
  • 问题是,如果模板包含一个 指令时,Velocity找不到“MyInclude.vm”,并抛出ResourceNotFoundException。 因为在getTemplate的参数中,我必须将包名前置到模板名之前,所以我也尝试在模板内的#include中执行同样的操作: 它听起来很像一个环境变量,但我不知道应该将它设置为什么,因为我使用的是ClasspathResourceLoader,并且要包含

  • 问题内容: 我正在为使用Jinja模板的服务器使用Flask微框架。 我有一个家长和孩子们的一些所谓的模板和,这些孩子有的模板是相当大的HTML文件,我想以某种分裂他们超过我的工作更好的洞察力。 我的脚本内容: The magic is in : 魔力在于child1.html: 而不是评论: 我有很多html文本,很难跟踪更改并且不犯一些错误,因此很难查找和纠正。 我只想加载而不是全部写入。 我

  • 问题内容: 我是Django的新手,我正尝试通过一个正在开发的简单项目“ dubliners”和一个名为“ book”的应用程序来学习它。目录结构是这样的: 我有一个JPG文件,需要在每个网页的页眉中显示。我应该在哪里存储文件?我应该使用哪个路径来使用模板显示标签?我已经尝试过各种位置和路径,但到目前为止没有任何效果。 … 感谢您在下面发布答案。但是,我尝试了图像的相对路径和绝对路径,但仍然在网页

  • 问题内容: 我最近开始学习Go。我有一个像网络应用程序这样的示例。我有: 我无法加载本地。当我写的时候它被加载了。如何加载本地js文件?我不擅长使用Go编写代码,也没有编写完整的代码。因此,请尝试解释非常简单。提前致谢! 问题答案: 您需要a 或a 来在请求时将文件内容()发送到Web浏览器。 您有3种选择: 手动执行 这是更复杂的解决方案。就像在处理程序函数中,您读取文件的内容,设置适当的响应内

  • 我有一个Apache camel应用程序,它在rest服务和web服务之间进行中介。Rest服务是调用方,web服务是后端。我已经取得了进展,直到我从web服务获得响应,并将其转换为XML。现在,我必须以特定的格式(例如,使用一些附加的事务和会话ID)向调用方发送JSON响应,从XML中提取数据。对此我有什么选择?是否有可用的工具可以使用XSD创建脚本化的JSON模板,或者我必须手动编写脚本?如果

  • 我有一个非常特殊的例子,我需要在一个模板文本中使用一个模板文本,但是我做不到。 代码如下所示: 然而,我必须将其包装在函数中,同时保持变量的值,这会导致错误发生。无论我是否逃脱了滴答声。 使用转义滴答,我收到以下错误消息: 错误:预期的某个链接但未提供 没有,我得到: 意外标记,预期“”,” 我该怎么处理这件事? 编辑:可能应该注意的是,中传递的代码将被渲染并且需要使用它。它最终将通过传递给另一个