【问题标题】:Velocity template metadata速度模板元数据
【发布时间】:2018-03-20 14:47:01
【问题描述】:

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

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

我尝试使用文字 #[[...]]# 块(并解析它们)和 #set 指令,但两者都有问题。它们很老套(需要对模板进行一些解析)并且远非优雅。

【问题讨论】:

    标签: java apache metadata velocity


    【解决方案1】:

    嗯,我不知道有什么内置的东西可以做到这一点。不过,为了避免在第一次通过时处理整个模板,一个技巧是在该次通过期间有条件地抛出异常(下面的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 项目似乎正在消亡。
    猜你喜欢
    • 2013-06-10
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    • 2012-03-20
    • 2023-03-06
    • 2015-09-17
    相关资源
    最近更新 更多