Оценка Mvel
Постановка задачи: скажем, у меня есть выражение (a + b + c)
и я хочу вычислить его значение и присвоить какую-то переменную. Позже я хочу использовать значение этой переменной в другой логике. Все это делается через MVEL. Проблема, если кто-то из (a,b,c)
является 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
,
2 ответа
Проблема была решена, я фактически создавал статическую ссылку для VariableResolverFactory и обращался к ней одинаково для каждой оценки, я менял ее на новый экземпляр для каждого выполнения, и это работало.
public VariableResolverFactory getMvelFactory(Map contextMap) {
VariableResolverFactory functionFactory = new MapVariableResolverFactory(contextMap);
MVEL.eval("checkNullValue = def (x) { x == null ? 0 : x };", functionFactory);
return functionFactory;
}
Проблема с вашим троичным оператором. Я не уверен, как MVEL оценивает их (то, как вы их используете, было бы недопустимо в Java), но кажется, что помещение присваивания в часть then/else не работает... или, скорее, оно (по какой-либо причине) работает работать для части "тогда" (до :
), но терпит неудачу для части 'else' (после :
).
Так что, если сумма > 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