Оценка Mvel

Постановка задачи: скажем, у меня есть выражение (a + b + c)и я хочу вычислить его значение и присвоить какую-то переменную. Позже я хочу использовать значение этой переменной в другой логике. Все это делается через MVEL. Проблема, если кто-то из (a,b,c) является nullMVEL оценивает в строковом формате.

Поэтому, чтобы избежать этого, я создал свою собственную функцию для передачи каждого объекта и, если он равен нулю, обнуляю его.

Пример кода ниже

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
Другие вопросы по тегам