SpringElUtil 工具类

在项目中频繁使用SpringEL表达式进行数据解析,过滤等操作. 遂抽取工具类使用

Show me code



import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationContextException;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.expression.BeanExpressionContextAccessor;
import org.springframework.context.expression.BeanFactoryAccessor;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.context.expression.EnvironmentAccessor;
import org.springframework.context.expression.MapAccessor;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.expression.spel.support.StandardTypeLocator;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author boommanpro
 * @date 2020/12/17 17:51
 */
@Component
public class SpringElUtil implements ApplicationContextAware {

    private static final StandardEvaluationContext CONTEXT = new StandardEvaluationContext();

    private static final ExpressionParser EXPRESSION_PARSER = new SpelExpressionParser();

    static {
        CONTEXT.addPropertyAccessor(new BeanExpressionContextAccessor());
        CONTEXT.addPropertyAccessor(new BeanFactoryAccessor());
        CONTEXT.addPropertyAccessor(new MapAccessor());
        CONTEXT.addPropertyAccessor(new EnvironmentAccessor());
    }



    private static final ConcurrentHashMap<String, Expression> EXPRESSION_MAP = new ConcurrentHashMap<>();
    private static final ConcurrentHashMap<String, Expression> TEMPLATE_EXPRESSION_MAP = new ConcurrentHashMap<>();

    public static <T> T getValue(String expressionString) {
        return getValue(expressionString, null);
    }

    public static String getTemplateStringValue(String templateString, Map<String, Object> rootObject) {
        Expression expression = TEMPLATE_EXPRESSION_MAP.computeIfAbsent(templateString, s -> EXPRESSION_PARSER.parseExpression(s, new TemplateParserContext()));
        return expression.getValue(CONTEXT, rootObject, String.class);
    }

    @SuppressWarnings("all")
    public static <T> T getValue(String expressionString, Object rootObject) {
        Expression expression = getExpression(expressionString);
        return ((T) expression.getValue(CONTEXT, rootObject));
    }


    private static Expression getExpression(String expressionString) {
        return EXPRESSION_MAP.computeIfAbsent(expressionString, EXPRESSION_PARSER::parseExpression);
    }


    @Override
    @SuppressWarnings("all")
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        if (applicationContext instanceof ConfigurableApplicationContext) {
            ConfigurableApplicationContext ac = (ConfigurableApplicationContext) applicationContext;

            CONTEXT.setBeanResolver(new BeanFactoryResolver(ac.getBeanFactory()));
            CONTEXT.setTypeLocator(new StandardTypeLocator(ac.getBeanFactory().getBeanClassLoader()));
        } else {
            throw new ApplicationContextException("can't cast ConfigurableApplicationContext");
        }
    }
}


Example

#result = 1 + 2
#{6.0221415E+23D instanceof T(Double)}
intArray[idx]-- le 0xFF
{1, 2, 3}
(true and false) || variable not null ? 1.0f : 0.0f
Members.?[Nationality == 'Serbian']
'5.00' matches '\^-?\\d+(\\.\\d{2})?$'
new java.lang.String('stringLiteral')
${myPropertyKey}
@myBean.instanceMethod(1, 2)
T(String).CASE_INSENSITIVE_ORDER