深入淺出springEL表達式

深入淺出springEL表達式

什麼是SpringEL?

Spring3中引入了Spring表達式語言—SpringEL,SpEL是一種強大,簡潔的裝配Bean的方式,他可以通過運行期間執行的表達式將值裝配到我們的屬性或構造函數當中,更可以調用JDK中提供的靜態常量,獲取外部Properties文件中的的配置

為什麼要使用SpringEL?

我們平常通過配置文件或Annotaton注入的Bean,其實都可以稱為靜態性注入,試想一下,若然我Bean A中有變量A,它的值需要根據Bean B的B變量為參考,在這場景下靜態注入就對這樣的處理顯得非常無力,而Spring3增加的SpringEL就可以完全滿足這種需求,而且還可以對不同Bean的字段進行計算再進行賦值,功能非常強大

如何使用SpringEL?

SpringEL從名字來看就能看出,和EL是有點關係的,SpringEL的使用和EL表達式的使用非常相似,EL表達式在JSP頁面更方便的獲取後臺中的值,而SpringEL就是為了更方便獲取Spring容器中的Bean的值,EL使用${},而SpringEL使用#{}進行表達式的聲明。

使用SpringEL注入簡單值

public class TestSpringEL {

/*
* @Value註解等同於XML配置中的<property>標籤,
* SpringEL同樣支持在XML<property>中編寫
*/

// 注入簡單值,輸出num為5
@Value("#{5}")

private Integer num;

// 注入ID為testConstant的Bean
@Value("#{testConstant}")

private TestConstant Constant;

// 注入ID為testConstant Bean中的STR常量/變量
@Value("#{testConstant.STR}")
private String str;
}

使用SpringEL調用方法

public class TestSpringEL {

/*
* TestConstant類中有兩個方法重載,
* 返回值為String類型
*/

// 調用無參方法
@Value("#{testConstant.showProperty}")
private String method1;

// 有參接收字符串的方法
@Value("#{testConstant.showProperty('Hello')}")
private String method2;


/*
* 若然希望方法返回的String為大寫
*/
@Value("#{testConstant.showProperty().toUpperCase()}")
private String method3;

/*
* 若使用method3這種方式,若然showProperty返回為null,
* 將會拋出NullPointerException,可以使用以下方式避免
*/
@Value("#{testConstant.showProperty()?.toUpperCase}")
private String method4;

/*
* 使用?.符號代表若然左邊的值為null,將不執行右邊方法,
* 讀者可以靈活運用在其他場景,只要左邊可能返回null,
* 即可使用上面示例中的?.
*/
}

SpringEL調用靜態類或常量

public class TestSpringEL {
/*
* 注入JDK中的工具類常量或調用工具類的方法
*/

// 獲取Math的PI常量
@Value("#{T(java.lang.Math).PI")
private double pi;

// 調用random方法獲取返回值

@Value("#{T(java.lang.Math).random()}")
private double ramdom;

// 獲取文件路徑符號
@Value("#{T(java.io.File).separator}")
private String separator;
}

SpringEL運算

public class TestSpringEL {
/*
* 使用SpringEL進行運算及邏輯操作
*/

// 拼接字符串
@Value("#{testConstant.nickname + ' ' + testConstant.name}")
private String concatString;

// 對數字類型進行運算,testConstant擁有num屬性
@Value("#{ 3 * T(java.lang.Math).PI + testConstant.num}")
private double operation;

// 進行邏輯運算
@Value("#{testConstant.num > 100 and testConstant.num <= 200}")
private boolean logicOperation;

// 進行或非邏輯操作
@Value("#{ not testConstant.num == 100 or testConstant.num <= 200}")
private boolean logicOperation2;

// 使用三元運算符
@Value("#{testConstant.num > 100 ? testConstant.num : testConstant.num + 100}")
private Integer logicOperation3;
}

SpringEL使用正則表達式

public class TestSpringEL {
// 驗證是否郵箱地址正則表達式
@Value("#{testConstant.STR match '\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+'}")
private boolean regularExpression;
}

SpringEL操作集合

public class TestSpringEL {
/*
* TestConstant類中擁有名為testList的List變量, 和名為testMap的Map
*/

// 獲取下標為0的元素
@Value("#{testConstant.testList[0]}")
private String str;

// 獲取下標為0元素的大寫形式
@Value("#{testConstant.testList[0]?.toUpperCase()}")
private String upperStr;

// 獲取map中key為hello的value
@Value("#{testConstant.testMap['hello']}")
private String mapValue;

// 根據testList下標為0元素作為key獲取testMap的value
@Value("#{testConstant.testMap[testConstant.testList[0]]}")
private String mapStrByTestList;
}

Spring操作外部Properties文件



<properties>
1
2
3
4
public class TestSpringEL {
// 注意test為xml文件中聲明的id
@Value("#{test['jdbc.url']}")
private String propertiesValue;
}

SpringEL查詢篩選集合和投影

public class TestSpringEL {
/*
* 聲明City類,有population屬性 testContants擁有名叫cityList的City類List集合
*/

// 過濾testConstant中cityList集合population屬性大於1000的全部數據注入到本屬性
@Value("#{testConstant.cityList.?[population > 1000]}")
private List<city> cityList;

// 過濾testConstant中cityList集合population屬性等於1000的第一條數據注入到本屬性
@Value("#{testConstant.cityList.^[population == 1000]}")
private City city;

// 過濾testConstant中cityList集合population屬性小於1000的最後一條數據注入到本屬性
@Value("#{testConstant.cityList.$[population < 1000]}")
private City city2;

/*
* 首先為city增加name屬性,代表城市的名稱
*/

/*
* 假如我們在過濾城市集合後只想保留城市的名稱,

* 可以使用如下方式進行投影
*/
@Value("#{testConstant.cityList.?[population > 1000].![name]}")
private List<string> cityName;
}
/<string>/<city>

優點:

SpringEL功能非常強大,在Annotation的方式開發時可能感覺並不強烈,因為可以直接編寫到源代碼來實現SpringEL的功能,但若然是在XML文件中進行配置,SpringEL可以彌補XML靜態注入的不足,從而實現更強大的注入

缺點:

SpringEL在使用時僅僅是一個字符串,不易於排錯與測試,也沒有IDE檢查我們的語法,當出現錯誤時較難檢測

筆者實際應用:

筆者開發的項目當中比較頻繁的使用SpringEL,例如通過SpringEL獲取外部properties中的值,又或者項目當中的數據字典亦是使用SpringEL的一個場景,我們抽象出一個Param類的集合,通過SpringEL集合篩選和投影獲取我們想要的字段參數添加到我們的程序邏輯當中(筆者項目中的Spring Security亦使用SpringEL,但本文章不加以敘述)

總結:

Spring3.0讓人為之驚豔的非SpringEL莫屬,為我們的注入提供了另一種強大的形式,傳統注入能做到的事情,和做不到的事情,SpringEL一概能完成,但在項目當中並不適宜大量使用SpringEL,適當的技術方在適當的位置,才能更好的完成事情


分享到:


相關文章: