Freemarker:以编程方式读取一些模板参数

时间:2016-01-11 09:14:24

标签: java freemarker

我试图从Java中以编程方式读取一些freemarker模板值,如下所示:

public Map<String, Object> getRootAssignments() {
    Enumeration en = template.getRootTreeNode().children();

    Map<String, Object> map = new HashMap<>();
    while (en.hasMoreElements()) {
        Object next = en.nextElement();

        // instanceof private class does not work
        if (next.getClass().getSimpleName().equals("Assignment")) {
            map.put(getInternalState(next, "variableName").toString(), 
                    getInternalState(next, "value").toString());
        }
    }
    return map;
}



private Object getInternalState(Object o, String fieldName) {
    Field field = null;
    boolean wasAccessible = false;
    try {
        field = o.getClass().getDeclaredField(fieldName);
        wasAccessible = field.isAccessible();
        field.setAccessible(true);
        return field.get(o);
    } catch (Exception e) {
        return "";
    } finally {
        if (field != null) {
            field.setAccessible(wasAccessible);
        }
    }
}

有了这个,我可以轻松阅读<#assign variable = "value"/>。但是,一旦我需要获得一些需要评估的变量(例如<#assign variable = "first" + "second"/>),这显然不起作用。

实际上我并不喜欢这种方法,我宁愿在模板渲染后读取变量状态,因此不需要再次评估任何内容。这可行吗?

1 个答案:

答案 0 :(得分:1)

如果让freemarker.core.Environment保持活着,你可以读回变量值,如下所示:

Environment env = myTemplate.createProcessingEnvironment(root, out);
env.process();  // process the template
TemplateModel x = env.getVariable("x");

从最初的方法开始,请注意您使用的是标记为内部的API,这意味着没有长期向后兼容性保证。但真正脆弱的是用反思阅读私人领域。然后调用TemplateObject.getParameterCount / getParameterRole / getParameterValue会更稳定,因为它至少是一个API,即使是内部的。