SpEL是spring框架提供的表达式语言(expression language),用作spring框架或注解的一些配置。
因为近期在做代码分析,需用PLY对SpEL做语法解析,所以着重研究了一下SpEL的语法。记录一下,以便查阅。
语法
spel的关键字是不区分大小写的。
变量
#打头,比如#a
字面量
字符串字面量,用单引号括起,比如:‘hello’
整型和浮点型字面量:1 、 2.2
SPEL还特别提供了列表和字典的字面量:
一维列表: {1,2,3}
二维列表: {{1, 2, 3}, {4, 5, 6}}
字典: {'a':1, 'b':2}
字典里嵌套列表: {'a':{1,2,3}, 'b':2}
字典和列表支持多维和任意嵌套,像lua也不过就支持这些,SpEL对数据结构的支持还是很强的。
多写法的操作符
spel里有11个操作符是有两种写法的,一种是字母,一种是符号,列举如下:
RESERVED = {
"and": "AND",
"or": "OR",
"div": "DIV",
"eq": "EQ",
"ne": "NE",
"le": "LE",
"lt": "LT",
"ge": "GE",
"gt": "GT",
"mod": "MOD",
"not": "NOT"
}
t_NOT = r'!'
t_EQ = r'=='
t_NE = r'!='
t_LE = r'<='
t_LT = r'<'
t_GE = r'>='
t_GT = r'>'
t_MOD = r'%'
t_AND = r'&&'
t_OR = r'\|\|'
t_DIV = r'/'
spring框架的spel解析源码里对这些操作符做了特殊处理,比如:
class Tokenizer {
private static final String[] ALTERNATIVE_OPERATOR_NAMES = new String[]{"DIV", "EQ", "GE", "GT", "LE", "LT", "MOD", "NE", "NOT"};
...
and和or的特殊处理则是在语法解析部分,可参考spring源码的InternalSpelExpressionParser.eatLogicalAndExpression方法。
算术运算符和关系运算符
常用的四则运算、三目、比较以及与或运算符都有。这是一个EL的核心。
SPEL还有一些特殊的运算符,比如elvis运算符,它的写法是:
expr1 ?: expr2
等价于:
expr1!=null ? expr1 : expr2
还有一个safe_navi运算符,写法是:
owner?.attr
?.会判断owner是否为null,如是,直接返回null。
SPEL还特别提供了一个正则匹配符matches,可做正则表达式的匹配,能力还是很强的。
java里调用SPEL的样例
使用SpelExpressionParser即可。
SpelExpressionParser parser = new SpelExpressionParser();
Expression expr = parser.parseExpression("2 > 1 ");
System.out.println(expr.getValue());
用途
1、spring的配置语言,像@Cacheable、@Value等注解里都有用到。
2、作为内嵌脚本,执行一些业务逻辑,比如某种阈值判定。
3、内嵌到其它语言中,作为扩展。Spring提供了TemplateParserContext类,可以很方便做到这一点。