1

我有一个应用程序,其中包含一些用于编程配置的 EL 评估。给定一个 EL 表达式,我想在不实际评估它的情况下获得它包含的自由变量。目的是提供一个 UI,最终用户可以在按下“评估”按钮之前将值绑定到自由变量。

不幸javax.el.ValueExpression的是不提供这个功能,所以我可能需要使用特定于供应商的 API。它还处于开发的早期阶段,所以我还没有确定我的实现选择。我想到了 MVEL、JUEL 和 SpEL,但当然我选择的任何东西都应该具有我上面描述的功能。

4

3 回答 3

3

这个怎么样...

    SpelExpression parseExpression = (SpelExpression) new SpelExpressionParser().parseExpression(expressionString);
    SpelNode node = parseExpression.getAST();
    List<String> vars = getVars(node);

...


private List<String> getVars(SpelNode node) {
    List<String> vars = new ArrayList<String>();
    for (int i = 0; i < node.getChildCount(); i++) {
        SpelNode child = node.getChild(i);
        if (child.getChildCount() > 0) {
            vars.addAll(getVars(child));
        }
        else {
            if (child instanceof VariableReference) {
                vars.add(child.toStringAST());
            }
        }
    }
    return vars;
}
于 2012-08-06T14:04:50.887 回答
1

Gary 的回答很好,但是当表达式包含单个变量时,它对我不起作用,例如“#var”(一个没有子节点的节点)。一个小改动:

private Set<String> getVars(SpelNode node) {
    Set<String> vars = new HashSet<String>();
    if (node == null) {
        return vars;
    }

    if (node instanceof VariableReference) {
        // Remove the "#" to get the actual variable name
        vars.add(StringUtils.remove(node.toStringAST(), "#"));
    }

    for (int i = 0; i < node.getChildCount(); i++) {
        SpelNode child = node.getChild(i);
        vars.addAll(getVars(child));
    }

    return vars;
}
于 2012-11-07T17:19:06.387 回答
1

MVEL 的 ParserContext 可以告诉你所有关于由本地和输入组织的变量。

ParserContext ctx = ParserContext.create();
MVEL.analysisCompile("a = 0; b = 0;", ctx);

HashMap<String, Class> vars = ctx.getVariables();

assert vars.containsKey("a") && Number.class.isAssignableFrom(vars.get("a"));
assert vars.containsKey("b") && Number.class.isAssignableFrom(vars.get("b"));
于 2012-08-12T22:03:52.360 回答