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

Freemarker: read some template parameters programmatically

我正在尝试以编程方式从 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"/>),这显然是行不通的。

事实上我不太喜欢这种方法,我更愿意在模板渲染之后读取变量状态,这样就不必再次计算任何内容。可行吗?

如果让 freemarker.core.Environment 保持活动状态,您可以读回变量值,如下所示:

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

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