问题陈述:假设我有一个表达式(a + b + c)
,我想计算它的值并分配给某个变量。后来我想在其他逻辑中使用该变量值。这一切都是通过MVEL完成的。问题是如果(a,b,c)
之外的任何人都是null
,MVEL将以字符串格式进行评估。
为了避免这种情况,我创建了自己的函数来传递每个对象,如果它是null,则将其设为零。
以下示例代码
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
。
答案 0 :(得分:2)
问题出在您的三元运营商身上。我不确定MVEL如何评估那些(你使用它们的方式在Java中是非法的),但似乎将赋值放在then / else部分不起作用......或者更确切地说,它(无论出于何种原因)< em> 适用于&#39;然后&#39; part(在:
之前)但是对于&#39; else&#39;部分(在:
之后)。
因此,如果总和为> 2
,则无论您是否使用空检查功能,它都会失效。
您应该修复表达式并将赋值放在三元运算符前面:
MVEL.compileExpression("d = cnv(a) + cnv(b) + cnv(c) > 2 ? 2 : 3")
更新:一般来说,这是我观察到的,与a
,b
,c
和cnv
无关:
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
答案 1 :(得分:0)
问题得到解决,我实际上是为VariableResolverFactory创建静态引用,并且每次评估都引用相同的内容,我为每次执行都将其更改为新实例并且它有效。
public VariableResolverFactory getMvelFactory(Map contextMap) {
VariableResolverFactory functionFactory = new MapVariableResolverFactory(contextMap);
MVEL.eval("checkNullValue = def (x) { x == null ? 0 : x };", functionFactory);
return functionFactory;
}