Velocity模板元数据

3

Apache Velocity 是否包含向模板添加元数据的机制?

我正在尝试向我的模板添加一些额外信息(例如,类型和描述性名称),然后通过编程读取这些信息来按类型分组模板,并使用它们的描述性名称在 UI 上列出模板。

我已经尝试使用字面量#[[...]]#块(并解析它们)和#set指令,但两者都存在问题。它们很麻烦(需要对模板进行一些解析),而且远非优雅。

1个回答

0
嗯,我不知道有任何内置的东西可以做到这一点。为了避免在第一次通过时处理整个模板,一个技巧是在该过程中有条件地抛出异常(如下所示的MetadataFinished),但不进行正常执行。
显然,这仍然需要预先编译整个模板,但这应该在执行时会很有用。
例如:
import org.apache.commons.io.output.NullWriter;

public class Metadata {

    private Map<String, Template> byKey = new LinkedHashMap<>();
    private Template currentTemplate;

    /** Callback from .vm */
    public void set(String key) throws MetadataFinished {
        // Only do this in addTemplate()
        if (currentTemplate != null) {
            byKey.put(key, currentTemplate);
            throw new MetadataFinished();
        }
    }

    public void addTemplate(Template template) {
        currentTemplate = template;
        try {
            Context context = new VelocityContext();
            context.put("metadata", this);
            template.merge(context, new NullWriter());
        } catch (MetadataFinished ex) {
            // Ignored
        } finally {
            currentTemplate = null;
        }
    }

    public void execute(String key) {
        Template template = byKey.get(key);

        Context context = new VelocityContext();
        PrintWriter pw = new PrintWriter(System.out);
        template.merge(context, pw);
        pw.flush();
    }

    // Extends Error to avoid Velocity adding a wrapping MethodInvocationException
    private static class MetadataFinished extends Error {
    }

    public static void main(String[] args) {
        Metadata metadata = new Metadata();

        VelocityEngine engine = new VelocityEngine();
        engine.setProperty("file.resource.loader.path", "/temp");
        engine.init();

        String[] fileNames = { "one.vm", "two.vm" };
        for (String fileName : fileNames) {
            Template template = engine.getTemplate(fileName);
            metadata.addTemplate(template);
        }

        metadata.execute("vm1");
        metadata.execute("vm2");
    }
}

那么在 one.vm 中:

$!metadata.set("vm1")##
-----------
This is VM1
-----------

## 这里看起来有点丑 - 它只是为了防止输出空行。如果可读性很重要,可以通过宏使其更加美观一些:

#metadata("vm2")
-----------
This is VM2
-----------

那个宏可以在全局的 VM_global_library.vm 中定义:

#macro( metadata $key )
$!metadata.set($key)#end

仅供参考,输出结果符合预期:

-----------
This is VM1
-----------
-----------
This is VM2
-----------

同意。使用Velocity没有一种清晰的实现方式。不管怎样,Velocity项目似乎正在逐渐消亡。 - izilotti

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接