目录
5. Spring SpEL表达式(Spring Expression Language,SpEL)
Spring SpEL表达式(Spring Expression Language,SpEL)
SpEL表达式
Spring 3引入了Spring表达式语言,是一个支持运行时查询和操作对象图的强大的表达式语言。能够以一种强大和简洁的方式将值装配到Bean属性和构造器参数中,在这个过程中所使用的表达式会在运行时计算得到值。
SpEL拥有很多特性,包括:
1.使用bean的ID来引用bean
2.调用方法和访问对象的属性
3.计算表达式的值,对值进行算术、关系和逻辑运算
4.正则表达式匹配
5.集合操作
总得来说SpEL表达式是一种简化开发的表达式,通过使用表达式来简化开发,减少一些逻辑、配置的编写。
语法类似于EL,SpEL使用“
#{ … }
”作为定界符,所有在大括号中的字符都将被认为是SpEL,SpEL为bean的属性进行动态赋值提供了便利。
<bean id="car" class="com.my.Car">
<property name="brand" value="#{'玛莎拉蒂'}"/>
<property name="price" value="#{32000.78}"/>
<property name="perimeter" value="#{T(java.lang.Math).PI * 75.8f}"/>
</bean>
<bean id="person" class="com.my.Car">
<property name='name' value='#{"华崽儿"}'></property>
<property name="age" value="#{25}"></property>
<property name="marriage" value="#{car.price > 400000 and age > 30}"/>
<property name="car" value="#{car}"></property>
<property name="socialStatus" value="#{car.price > 30000 ? '金领' : '白领'}"/>
<property name="address" value="#{address.province + '省' + address.city + '市' + address.area + '区'}"/>
</bean>
<bean id="address" class="com.my.Car">
<property name="province" value="#{'辽宁'}"/>
<property name="city" value="#{'大连'}"/>
<property name="area" value="#{'沙河口'}"/>
</bean>
SpEL字面量
(1)整数:
#{8}
(2)小数:
#{8.8}
(3)科学计数法:
#{1e4}
(4)String:
#{‘字符串’}、#{“字符串”}
。可以使用单引号/双引号作为字符串的定界符号
(5)Boolean:
#{true}
SpEL引用bean属性和方法
(1)引用其他对象
#{car}
。car其他bean的ID
(2)引用其他对象的属性
#{car.brand}
。brand为bean#car的属性。
(3)调用对象其它方法,还可以链式操作
#{car.getName()}
。调用car实例的toString()方法
对于被调用方法的返回值来说,同样可以调用它的方法。调用toUpperCase()将字符串全部改成大写。
#{car.getName().toUpperCase()}
如果getName()的返回值是null的话,将会出现NullPointerException异常,可以使用类型安全的运算符
#{car.getName()?.toUpperCase()}
与之前只是使用点号(.)来访问toUpperCase()方法不同,现在使用了“?.”运算符。这个运算符能够在访问它右边的内容之前,确保它所对应的元素不是null。所以,如果selectArtist()的返回值是null的话,那么SpEL将不会调用toUpperCase()方法。表达式的返回值会是null。
(4)调用静态方法静态属性
如果要在SpEL中访问类作用域的方法和常量的话,要依赖T()这个关键的运算符
// 将PI值装配到bean属性中
#{T(java.lang.Math).PI}
// 计算得到一个0到1之间的随机数
#{T(java.lang.Math).random()}
SpEL支持的运算符号
(1)算术运算符
+、-、*、/、%、^(加号还可以用作字符串连接)
(2)比较运算符
<、> 、==、>=、<=、lt、gt、eg、le、ge
#{counter.total == 100}
#{counter.total eq 100}
比较两个数字是不是相等,可以双等号、文本型的eq运算符,表达式的计算结果是个Boolean值。
(3)逻辑运算符
and 、or 、not 、|
(4)if-else 运算符
(类似三目运算符):?:(temary),?:(Elvis)
#{car.Sorce > 50 ? "winner" : "loser"}
三元运算符的一个常见场景就是检查null值,并用一个默认值来替代null。
#{disc.title ?:"Rattleand Hum"}
会判断disc.title的值是不是null,如果是null的话,那么表达式的计算结果就会是“Rattleand Hum”
(5)正则表达式
当处理文本时,有时检查文本是否匹配某种模式是非常有用的。SpEL通过matches运算符支持表达式中的模式匹配。matches运算符对String类型的文本(作为左边参数)应用正则表达式(作为右边参数)。
matches的运算结果会返回一个Boolean类型的值:如果与正则表达式相匹配,则返回true;否则返回false。
#{admin.email matches '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9._%+-]+\\.com'}
判断一个字符串是否包含有效的邮件地址。
集合
(1)引用列表中元素
#{box.song[4].title}
计算song集合中第五个(基于零开始)元素的title属性,这个集合来源于ID为box bean
(2)集合中随机选择
“[]”运算符用来从集合或数组中按照索引获取元素,还可以从String中获取一个字符
#{box.song[ T(java.lang.Math).random() * box.song.size() ].title}
引用了String中的第四个(基于零开始)字符,值为“s”
#{'this is a test' [3]}
查询运算符
(1).?[]
用来对集合进行过滤,得到集合的一个子集。
#{box.song.?[artist eq 'Aerosmith']}
希望得到box中artist属性为Aerosmith的所有song。
选择运算符在它的方括号中接受另一个表达式。当SpEL迭代歌曲列表的时候,会对歌曲集合中的每一个条目计算这个表达式。如果表达式的计算结果为true的话,那么条目会放到新的集合中。否则的话,它就不会放到新集合中。在本例中,内部的表达式会检查歌曲的artist属性是不是等于Aerosmith。
(2)“.^[]”和“.$[]”
分别用来在集合中查询第一个匹配项和最后一个匹配项
(3)投影运算符( .![])
从集合的每个成员中选择特定的属性放到另外一个集合中