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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章