3

问题陈述:假设我有一个表达式(a + b + c),我想计算它的值并分配给某个变量。稍后我想在其他逻辑中使用该变量值。这一切都是通过 MVEL 完成的。问题是如果有人不在(a,b,c)is 中null,MVEL 会以字符串格式计算。

所以为了避免这种情况,我创建了自己的函数来传递每个对象,如果它为空,则将其设为零。

下面的示例代码

public class MvelTest {

    public static void main(String[] args) {

        Map map = new HashMap();

        VariableResolverFactory functionFactory = new MapVariableResolverFactory(map);
        MVEL.eval("checkNullValue = def (x) { x == null ? 0 : x };", functionFactory);

        map.put("a", null);
        map.put("b", 1);
        map.put("c", 1);

        Serializable str = MVEL.compileExpression("( ( checkNullValue(a) + checkNullValue(b) + checkNullValue(c) ) > 2 ) ? d=2 : d=3");

        MVEL.executeExpression(str, map, functionFactory);
        System.out.println(map);
        System.out.println(map.get("d"));
    }
}

输出

{checkNullValue=function_prototype:null, b=1, c=1, a=null}
null

我无法获得"d"此处的值,如果我删除工厂和空值检查功能,它会运行并且我能够获得"d". 但是我必须使它对算术运算安全,因为 MVEL 不能处理这个。

此外(null * 23),MVEL 返回为false.

4

2 回答 2

2

问题出在您的三元运算符上。我不确定 MVEL 如何评估这些(在 Java 中使用它们的方式是非法的),但似乎将赋值放在 then/else 部分不起作用......或者更确切地说,它(无论出于何种原因)确实为“then”部分(之前:)工作,但为“else”部分(之后)失败:

因此,如果总和> 2有效,则无论您是否使用空值检查功能,否则它会失败。

您应该修复您的表达式并将赋值放在三元运算符前面:

MVEL.compileExpression("d = cnv(a) + cnv(b) + cnv(c) > 2 ? 2 : 3")

更新:通常,这是我观察到的,独立于abccnv

MVEL.compileExpression("true  ? d=1 : d=2"); // d ends up as 1
MVEL.compileExpression("false ? d=1 : d=2"); // d is null / unknown
MVEL.compileExpression("d = guard ? 1 : 2"); // always works
于 2014-06-16T14:16:14.143 回答
0

问题得到了解决,我实际上是在为 VariableResolverFactory 创建静态引用,并且每次评估都引用相同的引用,我将它更改为每次执行的新实例并且它有效。

 public VariableResolverFactory getMvelFactory(Map contextMap) {
        VariableResolverFactory functionFactory = new MapVariableResolverFactory(contextMap);
        MVEL.eval("checkNullValue = def (x) { x == null ? 0 : x };", functionFactory);

        return functionFactory;
    }
于 2014-06-17T05:44:40.853 回答