SPRing表達式語言使用
@(Spring)[spEL, Spring, 表達式語言]
Spring表達式語言使用基本概述spEL的功能概述spEL語法以xml為例字面值表達式字符串整型浮點型科學計數法boolean類型引用Bean屬性和方法引用其它對象引用其他對象的屬性調用其他方法調用靜態方法SpEL 支持的運算符號算數運算符 - 比較運算符 lt gt eq le ge邏輯運算符號 and or not If-else 運算符 ternary Elvis正則表達式matchesSpEL 對集合的支持環境獲取Collection 中的某個對象獲取Collection 中的子集-通過條件篩選注意新對象是一個新的Collection篩選子集獲取第一個獲取最后一個集合的投影將投影和篩選結合基于注解的spEL設置域屬性的默認值在方法構造方法參數中使用spEL解析接口及其使用spEL接口使用String對象方法調用對象屬性使用dot notation鏈式操作構造方法的使用取對象中的值
基本概述
百度百科。。。。。
spEL的功能概述
The expression language supports the following functionality:
Literal expressionsBoolean and relational OperatorsRegular expressionsClass expressionsaccessing properties, arrays, lists, mapsMethod invocationRelational operatorsAssignmentCalling constructorsBean referencesArray constructionInline listsInline mapsTernary operatorVariablesUser defined functionsCollection projectionCollection selectionTemplated expressionsPS:從官方文檔,可以看出spEL是一門非常強大的表達式語言,其不僅支持一般表達式語言常見的顯示數據功能,還支持像是正則表達式、對象操作、靜態方法、靜態字段、集合操作、集合投影、集合篩選等等高級特性。
spEL語法(以XML為例)
spEL使用#{<expression string>}
作為定界符,其中的字符就會被識別為spEL。
字面值表達式
字符串
<property name="str1" value="#{'Hello World'}"/><property name='str2' value='#{"Hello World"}'/>整型
<property name="int" value="#{6}"/>浮點型
<property name="float" value="#{5.3}"/>科學計數法
<property name="c" value="#{6.0221415E+23}"/>boolean類型
<property name="bool" value="#{true}"/>引用Bean,屬性和方法
引用其它對象
<bean id=”saxophone” value=”com.xxx.xxx.Xxx”/><bean ..> <property name="instrument" value="#{saxophone}"/><bean/> 通過id:“saxophone”將對象注入到instrument 屬性中,這與下面的配置是一樣的:
<property name="instrument" ref="saxophone"/>引用其他對象的屬性
<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());調用其他方法
<property name="song" value="songSelector.selectSong()"/>調用了Bean的id為"songSelector"
的對象的selectSong()
方法,并將返回值注入到song 屬性 中。或者還可以鏈式操作。如下:
<property name="song" value="songSelector.selectSong().toUpperCase()"/>如果songSelector.selectSong()
返回null
的還會拋出異常,為了避免我們要使用?.表達式。 這樣如果songSelector.selectSong()
為null
就不會再調用后面的方法了。如下
<property name="song" value="songSelector.selectSong()?.toUpperCase()"/>調用靜態方法
我們已經知道如何通過一個對象調用它的方法了,但是如何調用一個靜態方法呢?用T()
。 它將返回一個 Class object
然后我們再調用相應的方法即可:
<property name="multjava.lang.Math).PI"/>SpEL 支持的運算符號
算數運算符:+, -, *, /, %, ^
<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}"/>加號還可以用作字符串連接
<property name="fullName" value="#{performer.firstName + ' ' + performer.lastName}"/>比較運算符: <, >, ==, <=, >=, lt, gt, eq, le, ge
<property name="equal" value="#{counter.total == 100}"/>不可以使用<和>號,應為在xml 中它有特殊的含義,我們使用lt 和gt 代替
<property name="hasCapacity" value="#{counter.total le 100000}"/>邏輯運算符號: 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}"/>If-else 運算符:?: (ternary), ?: (Elvis)
最基本的 ?:(這如同我們在使用EL 表達式語言):
<property name="instrument" value="#{songSelector.selectSong() == 'Jingle Bells' ? piano : ' Jingle Bells '}"/>變體的 ?:
<property name="song" value="#{kenny.song ?: 'Greensleeves'}"/>正則表達式:matches
<property name="validEmail" value="#{admin.email matches '[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+//.[a-zA-Z]{2,4}'}"/>表達式返回邏輯值,如果匹配返回true,否則返回false
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=" Cruces" p:state="NM" p:population="91865"/></util:list>獲取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]獲取Collection 中的子集-通過條件篩選(注意新對象是一個新的Collection)
篩選子集(.?[])
<property name="bigCities" value="#{cities.?[population gt 100000]}"/>獲取第一個(.^[])
<property name="aBigCity" value="#{cities.^[population gt 100000]}"/>獲取最后一個(.$[])
<property name="aBigCity" value="#{cities.$[population gt 100000]}"/>集合的投影(.![])
如果想獲得所有城市的名稱組成的列表,可用如下操作
<property name="cityNames" value="#{cities.![name]}"/>將返回"Chicago", "Atlanta", "Dallas"
也可以組合兩個列,如下:
<property name="cityNames" value="#{cities.![name + ', ' + state]}"/>將返回"Chicago, IL", "Atlanta, GA", and "Dallas, TX"
將投影和篩選結合
<property name="cityNames" value="#{cities.?[population gt 100000].![name + ', ' + state]}"/>PS:這部分是從是從某pdf中整理出來的,該pdf是參考別人博客的,沒有寫明參考,敬請見諒。
基于注解的spEL
使用@Value
注解可以放在域、方法、方法/ 構造方法參數作為默認值。
設置域屬性的默認值
public static class FieldValueTestBean { @Value("#{ systemProperties['user.region'] }") private String defaultLocale; public void setDefaultLocale(String defaultLocale) { this.defaultLocale = defaultLocale; } public String getDefaultLocale() { return this.defaultLocale; }}與以下代碼等價
public static class PropertyValueTestBean { private String defaultLocale; @Value("#{ systemProperties['user.region'] }") public void setDefaultLocale(String defaultLocale) { this.defaultLocale = defaultLocale; } public String getDefaultLocale() { return this.defaultLocale; }}在方法/構造方法參數中使用
public class SimpleMovieLister { private MovieFinder movieFinder; private String defaultLocale; @Autowired public void configure(MovieFinder movieFinder, @Value("#{ systemProperties['user.region'] }") String defaultLocale) { this.movieFinder = movieFinder; this.defaultLocale = defaultLocale; } // ...}public class MovieRecommender { private String defaultLocale; private CustomerPreferenceDao customerPreferenceDao; @Autowired public MovieRecommender(CustomerPreferenceDao customerPreferenceDao, @Value("#{systemProperties['user.country']}") String defaultLocale) { this.customerPreferenceDao = customerPreferenceDao; this.defaultLocale = defaultLocale; } // ...}spEL解析接口及其使用
Spring表達式語言的解析接口為ExpressionParser
,是用來解析spEL表達式的,在org.springframework.expression
包下,其實現類SpelExpressionParser
,在它的子包spel.support
下。
spEL接口使用
通過該接口中的一些方式,我們能在java代碼中操縱spEL。其使用方式如下:
String
// 創建對象ExpressionParser parser = new SpelExpressionParser();// 解析表達式Expression exp = parser.parseExpression("'Hello World'");// 獲取結果String message = (String) exp.getValue();對象方法調用
ExpressionParser parser = new SpelExpressionParser();Expression exp = parser.parseExpression("'Hello World'.concat('!')");String message = (String) exp.getValue();對象屬性使用
ExpressionParser parser = new SpelExpressionParser();// invokes 'getBytes()'Expression exp = parser.parseExpression("'Hello World'.bytes");byte[] bytes = (byte[]) exp.getValue();dot notation鏈式操作
ExpressionParser parser = new SpelExpressionParser();// invokes 'getBytes().length'Expression exp = parser.parseExpression("'Hello World'.bytes.length");int length = (Integer) exp.getValue();構造方法的使用
ExpressionParser parser = new SpelExpressionParser();Expression exp = parser.parseExpression("new String('hello world').toUpperCase()");String message = exp.getValue(String.class);PS:注意,構造方法獲取其值時,可以通過public <T> T getValue(Class<T> desiredResultType)
該方法來轉換類型。
取對象中的值
// Create and set a calendarGregorianCalendar c = new GregorianCalendar();c.set(1856, 7, 9);// The constructor arguments are name, birthday, and nationality.Inventor tesla = new Inventor("Nikola Tesla", c.getTime(), "Serbian");ExpressionParser parser = new SpelExpressionParser();Expression exp = parser.parseExpression("name");EvaluationContext context = new StandardEvaluationContext(tesla);String name = (String) exp.getValue(context);// Create and set a calendarGregorianCalendar c = new GregorianCalendar();c.set(1856, 7, 9);// The constructor arguments are name, birthday, and nationality.Inventor tesla = new Inventor("Nikola Tesla", c.getTime(), "Serbian");ExpressionParser parser = new SpelExpressionParser();Expression exp = parser.parseExpression("name");String name = (String) exp.getValue(tesla);PS:在spEL中,被取值的對象,被叫做根對象(root object)。通過EvaluationContext
接口可以設置其需要解析的根對象,也可以直接通過Object getValue(Object rootObject)
來指明需要獲取的是哪個對象的值。
——參考《Spring Framework Reference Documentation 4.3.3.RELEASE》