教自己学习SpEL表达式

各位看官可以关注博主个人博客,了解更多信息。
作者:Surpasser
链接地址:https://surpass.org.cn

image

Spring 3.0 创建了一种新的方式用以配置对象的注入(set 注入或者构造参数注入),它便是 SpEL (Spring Expression Language)下面我们一一做一介绍。

基础特性

SpEL 使用#{…}作为定界符,所有在大框号中的字符都将被认为是 SpEL.

1、 自变量的表示

1、整数

<name="count" value="#{5}"/>

2、小数

<name="frequency" value="#{89.7}"/>

3、科学计数法

<name="capacity" value="#{1e4}"/>

4、String 可以使用单引号或者双引号作为字符串的定界符号。

<name="name" value="#{'Chuck'}"/> 
<name='name' value='#{"Chuck"}'/> 

5、Boolean

<name="enabled" value="#{false}"/>

2、 引用 Bean,属性和方法

1、引用其他对象

<id=”saxophone” value=”com.xxx.xxx.Xxx”/> 
<bean ..>
<property name="instrument" value="#{saxophone}"/>
<bean/>   

​ 通过id:“saxophone”将对象注入到instrument 属性中,这与下面的配置是一样的:

<name="instrument" ref="saxophone"/>

2、引用其他对象的属性

<bean id="carl" class="com.springinaction.springidol.Instrumentalist">
<property name="song" value="#{kenny.song}" /> 
</bean>  

​ kenny 是Bean Id 而 song 是属性的名字,这样配置就如同我们写了如下的代码

Instrumentalist carl = new Instrumentalist(); 
carl.setSong(kenny.getSong());  

3、调用其他方法

<property name="song" value="songSelector.selectSong()"/>

​ 调用了 BeanId 为“songSelector”的对象的selectSong()方法,并将返回值注入到 song 属性

​ 中。或者还可以链式操作。如下:

<property name="song" value="songSelector.selectSong().toUpperCase()"/>

​ 如果 songSelector.selectSong()返回 null 的还会抛出异常,为了避免我们要使用?.表达式。

​ 这样如果 songSelector.selectSong()为null 就不会再调用后面的方法了。如下

<property name="song" value="songSelector.selectSong()?.toUpperCase()"/>

4、调用静态方法

我们已经知道如何通过一个对象调用它的方法了,但是如何调用一个静态方法呢?用T()。它将返回一个 Class object

然后我们再调用相应的方法即可:

<property name="multiplier" value="T(java.lang.Math).PI"/> 

3、SpEL 支持的运算符号

1、算数运算符:+, -, *, /, %, ^

<property name="adjustedAmount" value="#{counter.total + 42}"/> 
<property name="adjustedAmount" value="#{counter.total - 20}"/> 
<property name="circumference" value="#{2 * T(java.lang.Math).PI * circle.radius}"/> 
<property name="average" value="#{counter.total / counter.count}"/> 
<property name="remainder" value="#{counter.total % counter.count}"/> 
<property name="area" value="#{T(java.lang.Math).PI * circle.radius ^ 2}"/>

​ 加号还可以用作字符串连接

  1. <property name="fullName" value="#{performer.firstName + ' ' + performer.lastName}"/>

2、比较运算符: <, >, ==, <=, >=, lt, gt, eq, le, ge

<property name="equal" value="#{counter.total == 100}"/>

​ 不可以使用<和>号,应为在 xml 中它有特殊的含义,我们使用 lt 和 gt 代替

<property name="hasCapacity" value="#{counter.total le 100000}"/>

3、 逻辑运算符号: and, or, not, |

<property name="largeCircle" value="#{shape.kind == 'circle' and shape.perimeter gt 10000}"/> 
<property name="outOfStock" value="#{!product.available}"/> 
<property name="outOfStock" value="#{not product.available}"/>

4、 If-else 运算符:?: (ternary), ?: (Elvis)

​ 〇最基本的 ?:(这如同我们在使用EL 表达式语言):

<property name="instrument" value="#{songSelector.selectSong() == 'Jingle Bells' ? piano : ' Jingle Bells '}"/>

​ 〇变体的 ?:

<property name="song" value="#{kenny.song != null ? kenny.song : 'Greensleeves'}"/>

​ 上下两种是同一语义,但下面的明显简洁

<property name="song" value="#{kenny.song ?: 'Greensleeves'}"/> 

5、 正则表达式:matches

<property name="validEmail" value="#{admin.email matches '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}'}"/>

​ 表达式返回逻辑值,如果匹配返回 true,否则返回false

4、SpEL 对集合的支持

环境

​ 有实体 City 定义如下:

package com.habuma.spel.cities; 
public class City { 
private String name; 
private String state; 
private int population; 
} 

​ Xml 中有如下定义

<util:list id="cities"> 
<bean class="com.habuma.spel.cities.City" p:name="Chicago" p:state="IL" p:population="2853114"/>
<bean class="com.habuma.spel.cities.City" p:name="Atlanta" p:state="GA" p:population="537958"/>
<bean class="com.habuma.spel.cities.City" p:name="Dallas" p:state="TX" p:population="1279910"/>
<bean class="com.habuma.spel.cities.City" p:name="Houston" p:state="TX" p:population="2242193"/>
<bean class="com.habuma.spel.cities.City" p:name="Odessa" p:state="TX" p:population="90943"/>
<bean class="com.habuma.spel.cities.City" p:name="El Paso" p:state="TX" p:population="613190"/>
<bean class="com.habuma.spel.cities.City" p:name="Jal" p:state="NM" p:population="1996"/>
<bean class="com.habuma.spel.cities.City" p:name="Las Cruces" p:state="NM" p:population="91865"/>
<util:list>

1、 获取 Collection 中的某个对象〇通过下标访问,如下:

<property name="chosenCity" value="#{cities[2]}"/>

​ 我们就会获得 population 为"1279910"的city(记住下标从 0 开始) 〇下标可以通过变量指定,如下:

<property name="chosenCity" value="#{cities[T(java.lang.Math).random() * cities.size()]}"/> 

​ 〇如果是从 Map 中获得,可指定 key 值,如下

<property name="chosenCity" value="#{cities['Dallas']}"/> 

​ 〇也可以通过 key 访问 properties 的值,如下

<util:properties id="settings" location="classpath:settings.properties"/> 
<property name="accessToken" value="#{settings['twitter.accessToken']}"/>

​ 〇可以通过下标访问 systemEnvironment 和 SystemProperties 中的值

<property name="homePath" value="#{systemEnvironment['HOME']}"/> 

​ 〇如果在 jre 运行时配置了-Dapplication.home=/etc/myapp,我们可以通过如下方式访问

<property name="homePath" value="#{systemProperties['application.home']}"/>

​ 〇通过下标获取 String 串中的某个字符

This is a test'[3]

2、获取 Collection 中的子集-通过条件筛选(注意新对象是一个新的 Collection)

1、筛选子集(.?[])

<property name="bigCities" value="#{cities.?[population gt 100000]}"/>

2、获取第一个(.^[])

<property name="aBigCity" value="#{cities.^[population gt 100000]}"/>

3、获取最后一个(.$[])

<property name="aBigCity" value="#{cities.$[population gt 100000]}"/>

3、集合的投影(.![])

如果想获得所有城市的名称组成的列表,可用如下操作

<property name="cityNames" value="#{cities.![name]}"/> 

​ 将返回"Chicago", "Atlanta", "Dallas"

​ 也可以组合两个列,如下:

<property name="cityNames" value="#{cities.![name + ', ' + state]}"/>

​ 将返回"Chicago, IL", "Atlanta, GA", and "Dallas, TX".

4、将投影和筛选结合

<property name="cityNames" value="#{cities.?[population gt 100000].![name + ', ' + state]}"/> 
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,392评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,258评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,417评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,992评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,930评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,199评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,652评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,327评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,463评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,382评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,432评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,118评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,704评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,787评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,999评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,476评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,057评论 2 341