如何反省自由标记模板以找出它使用的变量? [英] How can I introspect a freemarker template to find out what variables it uses?

查看:97
本文介绍了如何反省自由标记模板以找出它使用的变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我完全不确定这是否是一个可解决的问题,但假设我有一个freemarker模板,我希望能够向模板询问它使用的变量。

I'm not at all sure that this is even a solvable problem, but supposing that I have a freemarker template, I'd like to be able to ask the template what variables it uses.

出于我的目的,我们可以假设freemarker模板非常简单 - 只是根级条目(这种模板的模型可以是一个简单的Map)。换句话说,我不需要处理调用嵌套结构的模板等。

For my purposes, we can assume that the freemarker template is very simple - just "root level" entries (the model for such a template could be a simple Map). In other words, I don't need to handle templates that call for nested structures, etc.

推荐答案

我有同样的任务从java端获取模板中的变量列表,除了使用反射之外,没有找到任何好的方法。我不确定是否有更好的方法来获取这些数据,但这是我的方法:

I had the same task to get the list of variables from template on java side and don't found any good approaches to that except using reflection. I'm not sure whether there is a better way to get this data or not but here's my approach:

public Set<String> referenceSet(Template template) throws TemplateModelException {
    Set<String> result = new HashSet<>();
    TemplateElement rootTreeNode = template.getRootTreeNode();
    for (int i = 0; i < rootTreeNode.getChildCount(); i++) {
        TemplateModel templateModel = rootTreeNode.getChildNodes().get(i);
        if (!(templateModel instanceof StringModel)) {
            continue;
        }
        Object wrappedObject = ((StringModel) templateModel).getWrappedObject();
        if (!"DollarVariable".equals(wrappedObject.getClass().getSimpleName())) {
            continue;
        }

        try {
            Object expression = getInternalState(wrappedObject, "expression");
            switch (expression.getClass().getSimpleName()) {
                case "Identifier":
                    result.add(getInternalState(expression, "name").toString());
                    break;
                case "DefaultToExpression":
                    result.add(getInternalState(expression, "lho").toString());
                    break;
                case "BuiltinVariable":
                    break;
                default:
                    throw new IllegalStateException("Unable to introspect variable");
            }
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new TemplateModelException("Unable to reflect template model");
        }
    }
    return result;
}

private Object getInternalState(Object o, String fieldName) throws NoSuchFieldException, IllegalAccessException {
    Field field = o.getClass().getDeclaredField(fieldName);
    boolean wasAccessible = field.isAccessible();
    try {
        field.setAccessible(true);
        return field.get(o);
    } finally {
        field.setAccessible(wasAccessible);
    }
}

我为演示模板内省而做的示例项目可以是在github上找到: https://github.com/SimY4/TemplatesPOC.git

Sample project that I made for demonstrating template introspection can be found on github: https://github.com/SimY4/TemplatesPOC.git

这篇关于如何反省自由标记模板以找出它使用的变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆