Apache Velocity 禁用模板和资源缓存

Apache Velocity disable template & resource caching

我有一个 Spring 启动应用程序,它公开了一个 API 来呈现一个相对简单的速度模板。该模板使用 #parse 来包含几个其他模板,否则会写出一些从 Java 层传递给它的基本变量。模板位于 JAR 文件中,因此它们是从 class 路径加载的。我使用以下根据请求即时创建的速度引擎设置:

    VelocityEngine ve = new VelocityEngine();
    ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
    ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
    ve.setProperty("classpath.resource.loader.cache", "false");
    ve.setProperty("velocity.engine.resource.manager.cache.enabled", "false");
    ve.setProperty("resource.manager.cache.enabled", "false");
    ve.init();

模板的多个部分对于每个请求都是唯一的(资源用作对简单 Spring MVC 控制器的响应),因此我需要禁用模板资源的缓存。我已经按原样尝试了上述配置,并在 src/main/resources 中的 velocity.properties 文件中定义了它,但是更改模板或文件不会 "take effect" 直到我重新启动应用程序.

按照 this documentation 页面上的说明似乎没有帮助(实际上您可以在上面看到它的作用)。

上面的引擎代码在 Spring Component class 中,甚至在将 VelocityEngine 内容移动到静态最终字段并仅初始化每个速度上下文时时间没有帮助。

如何强制 Spring/Velocity 每次加载模板和包含的资源?

您只需要 classpath.resource.loader.cache 配置密钥。由于 Velocity 中的所有缓存都默认为 false,因此您甚至不需要它。

此外,无需在每次请求时重新初始化 VelocityEngine。

我使用以下小测试程序检查了资源在修改后正确重新加载的位置:

import java.io.PrintWriter;
import java.io.Writer;
import java.util.Scanner;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;    

public class Test
{
    public static void main(String args[])
    {
        try
        {
            VelocityEngine ve = new VelocityEngine();
            ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
            ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
            // next line not needed since 'false' is the default
            // ve.setProperty("classpath.resource.loader.cache", "false");
            ve.init();

            VelocityContext context = new VelocityContext();
            Writer writer = new PrintWriter(System.out);
            Scanner scan = new Scanner(System.in);
            while (true)
            {
                System.out.print("> ");
                String str = scan.next();
                context.put("foo", str);
                ve.mergeTemplate("test.vm", "UTF-8", context, writer);
                writer.flush();
            }
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
    }
}

如果它在您的情况下不起作用,并且 特别是 如果您在每次请求时重新初始化 Velocity,那么它肯定是 Spring 中的 ClassLoader 缓存问题本身。

所以您应该检查 Spring Hot Swapping guide 以了解如何禁用缓存。我猜对 Spring 有更好了解的人可以为您提供有关如何处理这种特殊情况的提示。

令人尴尬的是,一旦更改模板或资源,我需要通过 IntelliJ 进行编译,例如使用 Ctrl+F9。感谢@Claude Brisson 的帮助。