Spring EL 小记(一)

原创
2016/03/24 21:02
阅读数 1.7K
import java.lang.reflect.Method;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
public class StudySpEL {
    
    
    public static void main(String[] args) {
        getStart();
        parseContext();
        regFunction();
    }
    
    public static void getStart() 
    {
        //待解析的字符串,注意整个字符串是要解析的,如果要解析的字符串中包含
        //字符串要使用单引号,例如要写成下面toParseString的样子而不是
        //"welcome to el world + #name"这样,因为不加引号,解析器
        //就会把它当做字段或者属性来解析,而没有这个属性或者字段就会出错
        final String toParseString = "'welcome to el world' + #name";
        
        //解析器,spring为我们提供了一个SpelExpressionParser解析器
        ExpressionParser parser = new SpelExpressionParser();
        
        //用解析器把待解析的字符串解析为表达式Expression 
        //Expression的结构就是一些AST节点,例如:"'welcome to el world' + #name"字符串
        //就被拆分为welcome to el wolrd #name这样的节点,方便被EvaluationContext计算
        Expression expression = parser.parseExpression(toParseString);
        
        //EvaluationContext就是计算的上下文,用来替换Expression中的变量表达式的
        //例如下面就是把待解析字符串(上下文)中的name变量替换为everybody
        EvaluationContext context = new StandardEvaluationContext();
        context.setVariable("name", "everybody");
        
        Object result = expression.getValue(context);
        System.out.println(result);
        
    }
    
    /**
     * 想spring中就会发现有 @Value("#{T(Math).PI * 4^2}") 这样的注解
     * 它的待解析的字符串是#{}这样的形式,怎么办,spring还有一个解析的上下文接口
     * ParserContext 它提供了一个默认的实现ParserContext.TEMPLATE_EXPRESSION
     * 就是解析以#{开头以}结束的字符串,当然也可以自己实现ParserContext接口
     */
    public static void parseContext()
    {
        //SpEL 支持+ - * / ^ % 等运算
        //SpEL 支持类型表达式 要求除了java.lang包以外的类使用类的全限定名称
        //T(Math).PI 就是访问java.lang.Math 的静态字段PI
        final String toParseString = "#{T(Math).PI * 4^2}";
        ExpressionParser parser = new SpelExpressionParser();
        
        //因为待解析字符串是#{}这样的形式所以使用ParserContext上下文,ParserContext.TEMPLATE_EXPRESSION
        Expression expression = parser.parseExpression(toParseString, ParserContext.TEMPLATE_EXPRESSION);
        Object value = expression.getValue(); //PI*16
        System.out.println(value);
    }
    
    /**
     * SpEL支持自定义函数,只能是静态方法
     */
    public static void  regFunction()
    {
        final String toParseString = "#customerFunction(4,6)";
        ExpressionParser parser = new SpelExpressionParser();
        Expression expression = parser.parseExpression(toParseString);
        
        StandardEvaluationContext context = new StandardEvaluationContext();
        Method customerFuction = null;
        try {
             customerFuction = StudySpEL.class.getDeclaredMethod("customerFunction", int.class,int.class);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        }
        //StandardEvaluationContext 才有registerFunction方法,也可以使用setVariable
        //注册方法
        context.registerFunction("customerFunction", customerFuction);
        Integer value = expression.getValue(context, int.class);
        System.out.println(value);
        
    }
    
    public static int customerFunction(int a,int b)
    {
        return a+b;
    }
}

      虽然我们平时可能很少用到很复杂的表达式,想解析mybatis的Mapper文件这种级别的,但是我们可以在注解上使用表达式,可以让注解有更多的动态特性,在结合aop,可以把一些实现做的很优雅。所以了解一点spring的EL总是没有坏处的。

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
4 收藏
1
分享
返回顶部
顶部