#Einschließen einer Datei aus einer Velocity-Vorlage mithilfe von ClasspathResourceLoader

Ich habe es mit Java-Code zu tun, bei dem Velocity 1.7 so eingestellt ist, dass Vorlagen über ClasspathResourceLoader abgerufen werden. Unten ist ein abgespecktes Beispiel des Codes. Es stammt aus einer Tapestry-Webanwendung, die auf einem Jetty-Server ausgeführt wird.

Die Java-Klasse, die Vorlagen und die Datei, die eingeschlossen werden sollen, befinden sich alle im selben Ordner "testpackage". In der resultierenden JAR befinden sie sich also alle im selben Paket "testpackage".

Das Problem ist, dass, wenn die Vorlage eine enthält

#include("MyInclude.vm")

Direktive kann Velocity "MyInclude.vm" nicht finden und löst eine ResourceNotFoundException aus.

Da ich im Argument von getTemplate den Paketnamen dem Vorlagennamen voranstellen muss, habe ich auch versucht, dies im # include innerhalb der Vorlage zu tun:

#include("testpackage/MyInclude.vm")

Der einzige Unterschied ist, dass Letzteres funktioniert, wenn ich die Web-App von Eclipse aus starte, während Ersteres nicht funktioniert, auch nicht von Eclipse aus. Wenn ich die JARs erstelle, bereitstelle und die Webanwendung über die Bereitstellung ausführe, schlagen beide Syntaxen mit derselben ResourceNotFoundException fehl.

Der Velocity-Doc beihttp://velocity.apache.org/engine/releases/velocity-1.7/user-guide.html#Include sagt:

"Aus Sicherheitsgründen befindet sich die einzubeziehende Datei möglicherweise nur unter TEMPLATE_ROOT."

Dies könnte definitiv die Ursache für mein Problem sein, aber ich konnte keine weiteren Informationen darüber finden, was TEMPLATE_ROOT tatsächlich ist.

Es klingt nach einer Umgebungsvariablen, aber ich weiß nicht, wie ich sie einstellen soll, da ich einen ClasspathResourceLoader verwende und die einzuschließende Datei keine tatsächliche Datei in einem Ordner ist, sondern sich in der JAR befindet mit den Vorlagen und der Java-Klasse (und alle im selben Paket).

Ich fand TEMPLATE_ROOT in einer anderen Frage erwähnt,Wo soll ich Velocity-Vorlagendateien für ein mit Maven erstelltes Befehlszeilendienstprogramm ablegen? , aber es hängt mit der Verwendung eines FileResourceLoader zusammen. Ich muss weiterhin den ClasspathResourceLoader verwenden und alle Dateien müssen sich in der JAR befinden, nicht außerhalb der normalen Dateien in einem Ordner.

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>

Antworten auf die Frage(1)

Ihre Antwort auf die Frage