SIA实战(一):SpEL的使用

####使用场合####
假设有这样一种情况,一个bean的某一个属性需要在程序运行的时候动态的赋值,使用SpEL将有效的简化开发。
在文章的结尾有工程源码,欢迎下载!

SpEL简介

SpEL是在Spring 3引入的新特性,全称为Spring Expression Language,它有许多强大的特性,包括:

  • 可以使用bean的ID来引用bean
  • 可以通过bean的ID来访问bean的属性和调用其方法
  • 可以进行关系,逻辑,算术运算
  • 正则表达式匹配
  • 对集合的操作

通过bean的ID来访问bean的属性和调用其方法

需求:一个购物清单(ShopList)用一个java bean封装,它的价格受到税率(Tax)影响,税率用单独的一个类封装
两个java bean的代码,省略getter和setter:

public class ShopList {
    private String name;
    private int count;
    private double price;
}

public class Tax {
    private double ctax;
}

接下来在spring配置文件中配置bean

<bean id="tax" class="com.yonyou.bean.Tax" p:ctax="10"></bean>

<bean id="list" class="com.yonyou.bean.ShopList" p:name="shanpoo" p:count="2" p:price="#{tax.ctax/100 * 36.5}"/>

可以看到p:price使用了#{},说明它是通过SpEL装配值的,tax.ctax说明这里使用了id为tax的ctax属性,以及后面的算术运算都是SpEL的应用。

我们不仅可以访问tax的属性,还可以调用它的方法,比如:p:price=”#{tax.getCtax()/100 * 36.5}”,使用“tax.getCtax()”

null-safe存取器
首先假设tax.getCtax()返回一个字符串,那么它可以接着调用,形如:tax.getCtax().trim()
但是如果tax.getCtax()返回为null,就会抛出空指针异常,为了避免异常,可以加一个“?”避免,即tax.getCtax()?.trim()

访问静态方法,静态变量
此时的SpEL需要使用以下形式访问静态方法,静态变量:
“#{T(类全名).静态方法}”
使用方法很简单,举两个例子,在Tax加一个静态方法getCountry()

p:name="#{T(com.yonyou.bean.Tax).country}"
p:name="#{T(com.yonyou.bean.Tax).getCountry()}"

主要说一个小坑:一开始我以为访问静态变量“.country”是访问类中的country静态变量,其实访问的还是getCountry()方法


运算符

SpEL支持绝大多数运算符,读者注意一下以下几点即可:

  1. 不要直接写”>”,”<”,转换为gt,lt
  2. +可以拼接字符串,字符串使用单引号
  3. 非运算可以使用“!”或“not”
  4. 可以使用java中的三元表达式,三元表达式常用于判断get出来的是否为null,比如name = vo.getName() == null ?”“:vo.getName(),vo.getName()需要竟然要写两遍!(博主的工作中经常这样写/(ㄒoㄒ)/~~ ),SpEL中可以这样写#{name = vo.getName()?’nothing’},如果vo.getName()为null就返回nothing,都不用写vo.getName()==null

SpEL使用正则表达式

比如校验邮箱:
“#{user.email matches \w{8,12}@\w{3,5}(\.[a-zA-Z]+){1,3}}”


筛选集合

SpEL可以将一个集合的子集装配到一个bean的属性中,这个集合可以是list,map,properties,系统变量等

1.util:list
首先简单说下util:list的作用:定义一个集合,让所有的bean共用,需要加入util约束,xmlns:util=”http://www.springframework.org/schema/util”
xsi:schemaLocation=”http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-4.2.xsd

重新定义两个java bean

public class Item {
    private String good;
    private double weight;
}
public class ShopList {
    ...
    private Item onlyOne;
}

在xml创建一个共用的Item集合(id=”its”),并且通过下标去引用集合里的元素,如“#{its[0]}”,xml中配置如下:

<util:list id="its">
            <bean class="com.yonyou.bean.Item" p:good="poke" p:weight="3.34"></bean>
            <bean class="com.yonyou.bean.Item" p:good="chicken" p:weight="5.66"></bean>
            <bean class="com.yonyou.bean.Item" p:good="dark" p:weight="3.64"></bean>
            <bean class="com.yonyou.bean.Item" p:good="egg" p:weight="2.54"></bean>
</util:list>

<bean id="list7" class="com.yonyou.bean.ShopList" p:name="#{tax.getName()?: 'bullshit'}" p:count="2"
         p:price="1" p:onlyOne="#{its[0]}"/><!-- 这里不是用ref装配 -->

有list的地方通常就有map,set,properties,所以也就有util:map,util:properties了,首先说下util:map

定义一个util:map:

<bean id="it1" class="com.yonyou.bean.Item" p:good="poke" p:weight="3.34"></bean>
<bean id="it2" class="com.yonyou.bean.Item" p:good="chicken" p:weight="5.66"></bean>

<util:map id="itmap">
    <entry key="poke" value-ref="it1">
    </entry>
    <entry key="chicken" value-ref="it2">
    </entry>
</util:map>

将key为chicken的bean注入到ShopList的onlyOne属性中:

<bean id="list8" class="com.yonyou.bean.ShopList" p:name="#{tax.getName()?: 'bullshit'}" p:count="2" p:price="1" p:onlyOne="#{itmap['chicken']}"/>

我们都知道Properties相对于Map来说,它的key,value都只能是String类型的,所以用法和Map差不多,不过在SpEL中允许直接从外部的一个properties文件中读取,更为方便

定义util:properties:

<util:properties id="itprop" location="classpath:spel.properites"/>

bean中使用

<bean id="list9" class="com.yonyou.bean.ShopList" p:name="#{itprop['username']}" p:price="1"/>

SpEL对于key-value的使用不止于此,还可以使用系统环境变量与java启动参数,分别使用systemEnvironmen和systemProperties,用法如:#{systemEnvironmen[‘HOME’]},#{systemProperties[‘application.home’]}等等


查询集合成员

购物结账时,发现钱没带够,此时我只想买重量小于3.5kg的食物,那么就要筛选购物条目了,只需要“.?[]”的方式即可,我们来查询下前面的util:list

<bean id="list10" class="com.yonyou.bean.ShopList" p:items="#{its.?[weight gt 3.5]}"/>

打印输出,发现确实只有小于3.5kg的食物

ShopList [name=null, count=0, price=0.0, items=[Item [good=poke, weight=3.34], Item [good=egg, weight=2.54]], onlyOne=null]

投影集合

我们再给ShopList增加一个属性:String[] allGood,现在要把util:list里所有item的good放到这个数组里,SpEL中使用“.![属性名]”就可以做到

<bean id="list11" class="com.yonyou.bean.ShopList" p:allGood="#{its.![good]}"/>

打印结果:allGood取到了所有的good值

ShopList [name=null, count=0, price=0.0, items=[], onlyOne=null, allGood=[poke, chicken, dark, egg]]

那个可不可以获取到所有小于3.5kg的所有条目的good呢?当然可以,结合两者即可
例如:<bean id="list12" class="com.yonyou.bean.ShopList" p:allGood="#{its.?[weight gt 3.5].![good]}"/>

输出结果:ShopList [name=null, count=0, price=0.0, items=[], onlyOne=null, allGood=[chicken, dark]]

好了,SIA中的SpEL我用12个小案例展示了一遍,如果大家有看不懂的地方请结合我的源码看,下面是地址:
http://download.csdn.net/detail/yj7758423/9751253

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值