當(dāng)前位置:
首頁(yè) >
Spring3的表达式语言
發(fā)布時(shí)間:2025/3/21
50
豆豆
生活随笔
收集整理的這篇文章主要介紹了
Spring3的表达式语言
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
Spring表達(dá)式語(yǔ)言全稱為“Spring Expression Language”,縮寫為“SpEL”,類似于Struts2x中使用的OGNL表達(dá)式語(yǔ)言,
能在運(yùn)行時(shí)構(gòu)建復(fù)雜表達(dá)式、存取對(duì)象圖屬性、對(duì)象方法調(diào)用等等,并能與Spring功能完美整合。表達(dá)式語(yǔ)言給靜態(tài)Java語(yǔ)言增加了動(dòng)態(tài)功能。
SpEL是單獨(dú)模塊,只依賴于core模塊,不依賴于其他模塊,可單獨(dú)使用。能干什么
表達(dá)式語(yǔ)言一般是用較為簡(jiǎn)單的形式完成主要的工作,減少開發(fā)的工作量。
SpEL支持如下表達(dá)式:
一、基本表達(dá)式:字面量表達(dá)式、關(guān)系,邏輯與算數(shù)運(yùn)算表達(dá)式、字符串連接及截取表達(dá)式、三目運(yùn)算及Elivis表達(dá)式、正則表達(dá)式、括號(hào)優(yōu)先級(jí)表達(dá)式;
二、類相關(guān)表達(dá)式:類類型表達(dá)式、類實(shí)例化、instanceof表達(dá)式、變量定義及引用、賦值表達(dá)式、自定義函數(shù)、對(duì)象屬性存取及安全導(dǎo)航表達(dá)式、對(duì)象方法調(diào)用、Bean引用;
三、集合相關(guān)表達(dá)式:內(nèi)聯(lián)List、內(nèi)聯(lián)數(shù)組、集合,字典訪問(wèn)、列表,字典,數(shù)組修改、集合投影、集合選擇;不支持多維內(nèi)聯(lián)數(shù)組初始化;不支持內(nèi)聯(lián)字典定義;
四、其他表達(dá)式:模板表達(dá)式。在Java中使用SpringEL是非常簡(jiǎn)單的,示例如下:
java代碼: public class HelloWorld { public static void main(String[] args) { //構(gòu)造上下文:準(zhǔn)備比如變量定義等等表達(dá)式運(yùn)行需要的上下文數(shù)據(jù) EvaluationContext context = new StandardEvaluationContext(); //創(chuàng)建解析器:提供SpelExpressionParser默認(rèn)實(shí)現(xiàn) ExpressionParser parser = new SpelExpressionParser(); //解析表達(dá)式:使用ExpressionParser來(lái)解析表達(dá)式為相應(yīng)的Expression對(duì)象 Expression expression = parser.parseExpression("('Hello' + ' World').concat(#end)"); //設(shè)置上下文中的變量的值 context.setVariable("end", "!SpringEL"); //執(zhí)行表達(dá)式,獲取運(yùn)行結(jié)果 String str = (String)expression.getValue(context); System.out.println("the str="+str); } } ExpressionParser接口 表示解析器,默認(rèn)實(shí)現(xiàn)是org.springframework.expression.spel.standard包中的SpelExpressionParser類,
使用parseExpression方法將字符串表達(dá)式轉(zhuǎn)換為Expression對(duì)象。 配合 ExpressionParser 接口使用的ParserContext接口用于定義字符串表達(dá)式是不是模板,及模板開始與結(jié)束字符,示例如下:java代碼: public static void main(String[] args) { ExpressionParser parser = new SpelExpressionParser(); //自定義一個(gè)解析模板的規(guī)則 ParserContext parserContext = new ParserContext() { public boolean isTemplate() { return true; } public String getExpressionPrefix() { return "#{"; } public String getExpressionSuffix() { return "}"; } }; String template = "#{'Hello '}#{'World!'}"; Expression expression = parser.parseExpression(template, parserContext); System.out.println( expression.getValue()); } 說(shuō)明 1:在此演示的是使用ParserContext的情況,此處定義了ParserContext實(shí)現(xiàn):定義表達(dá)式是模塊,表達(dá)式前綴為“#{”,后綴為“}”; 2:使用parseExpression解析時(shí)傳入的模板必須以“#{”開頭,以“}”結(jié)尾,如“#{‘Hello ’}#{‘World!’}”。 3:請(qǐng)注意默認(rèn)傳入的字符串表達(dá)式不是模板形式,如之前演示的Hello World。Expression接口 表示表達(dá)式對(duì)象,默認(rèn)實(shí)現(xiàn)是org.springframework.expression.spel.standard包中的SpelExpression,提供getValue方法用于獲取表達(dá)式值,提供setValue方法用于設(shè)置對(duì)象值EvaluationContext接口 表示上下文環(huán)境,默認(rèn)實(shí)現(xiàn)是org.springframework.expression.spel.support包中的StandardEvaluationContext類,使用setRootObject方法來(lái)設(shè)置根對(duì)象,
使用setVariable方法來(lái)注冊(cè)自定義變量,使用registerFunction來(lái)注冊(cè)自定義函數(shù)等等。字面量表達(dá)式:SpEL支持的字面量包括:字符串、數(shù)字類型(int、long、float、double)、布爾類型、null類型 ,示例如下:java代碼:1:String str1 = parser.parseExpression("'Hello World!'").getValue(String.class); 2:String str2 = parser.parseExpression("\"Hello World!\"").getValue(String.class); 3:int int1 = parser.parseExpression("1").getValue(Integer.class); 4:float float1 = parser.parseExpression("1.1").getValue(Float.class); 5:boolean true1 = parser.parseExpression("true").getValue(boolean.class); 6:Object null1 = parser.parseExpression("null").getValue(Object.class); 算數(shù)運(yùn)算表達(dá)式 : SpEL支持加(+)、減(-)、乘(*)、除(/)、求余(%)、冪(^)運(yùn)算,示例如下:1:int result1 = parser.parseExpression("1+2-3*4/2").getValue(Integer.class); 2:int result2 = parser.parseExpression(“4%3”).getValue(Integer.class) ; 3:int result3 = parser.parseExpression("2^3").getValue(Integer.class);SpEL還提供求余(MOD)和除(DIV)運(yùn)算符,與“%”和“/”等價(jià),不區(qū)分大小寫。關(guān)系表達(dá)式 等于(==)、不等于(!=)、大于(>)、大于等于(>=)、小于(<)、小于等于(<=),區(qū)間(between)運(yùn)算,示例如下: 1:“parser.parseExpression(”1>2“).getValue(boolean.class);”將返回false; 2:“parser.parseExpression(”1 between {1, 2}“).getValue(boolean.class);”將返回true。SpEL同樣提供了等價(jià)的“EQ” 、“NE”、 “GT”、“GE”、 “LT” 、“LE”來(lái)表示等于、不等于、大于、大于等于、小于、小于等于,不區(qū)分大小寫邏輯表達(dá)式:且(and)、或(or)、非(!或NOT)。 示例如下: 1:String expression1 = "2>1 and (!true or !false)"; boolean result1 = parser.parseExpression(expression1).getValue(boolean.class); 注意:邏輯運(yùn)算符不支持 Java中的 && 和 ||字符串連接及截取表達(dá)式 使用“+”進(jìn)行字符串連接,使用“‘String’ [index]”來(lái)獲取一個(gè)字符,目前只支持獲取一個(gè)字符, 如“'Hello ' + 'World!'”得到“Hello World!”;而“'Hello World!'[0]”將返回“H”三目運(yùn)算及Elivis運(yùn)算表達(dá)式 1:三目運(yùn)算符 “表達(dá)式1?表達(dá)式2:表達(dá)式3”用于構(gòu)造三目運(yùn)算表達(dá)式,如“2>1?true:false”將返回true; 2:Elivis運(yùn)算符“表達(dá)式1?:表達(dá)式2”從Groovy語(yǔ)言引入,用于簡(jiǎn)化三目運(yùn)算符的,當(dāng)表達(dá)式1為非null時(shí)則返回表達(dá)式1,當(dāng)表達(dá)式1為null時(shí)則返回表達(dá)式2,如“null?:false”將返回false,而“true?:false”將返回true;正則表達(dá)式 使用“str matches regex,如“‘123’ matches ‘\\d{3}’”將返回true;括號(hào)優(yōu)先級(jí)表達(dá)式 使用“(表達(dá)式)”構(gòu)造,括號(hào)里的具有高優(yōu)先級(jí)。類類型表達(dá)式 使用“T(Type)”來(lái)表示java.lang.Class實(shí)例,“Type”必須是類全限定名,“java.lang”包除外,即該包下的類可以不指定包名;
使用類類型表達(dá)式還可以進(jìn)行訪問(wèn)類靜態(tài)方法及類靜態(tài)字段。 示例如下: 1:訪問(wèn)java.lang包的類 Class<String> result1 = parser.parseExpression("T(String)").getValue(Class.class); 2:訪問(wèn)其他包下的類 : String expression2 = "T(cn.javass.spring.chapter5.SpELTest)";Class<String> result2 = parser.parseExpression(expression2).getValue(Class.class); 3:訪問(wèn)類的靜態(tài)字段 int result3=parser.parseExpression("T(Integer).MAX_VALUE").getValue(int.class); 4:訪問(wèn)類的靜態(tài)方法 int result4 = parser.parseExpression("T(Integer).parseInt('1')").getValue(int.class); 類實(shí)例化 類實(shí)例化同樣使用java關(guān)鍵字“new”,類名必須是全限定名,但java.lang包內(nèi)的類型除外,如String、Integer。示例如下: 1:String result1 = parser.parseExpression("new String('hello')").getValue(String.class); 2:Date result2 = parser.parseExpression("new java.util.Date()").getValue(Date.class);instanceof表達(dá)式 SpEL支持instanceof運(yùn)算符,跟Java內(nèi)使用同義;如“hello‘ instanceof T(String)”將返回true。變量定義及引用 1:變量通過(guò)EvaluationContext接口的setVariable(variableName, value)方法定義 2:在表達(dá)式中使用“#variableName”引用; 3:除了引用自定義變量,SpE還允許引用根對(duì)象及當(dāng)前上下文對(duì)象,使用“#root”引用根對(duì)象,使用“#this”引用當(dāng)前上下文對(duì)象; 示例如下:java代碼:ExpressionParser parser = new SpelExpressionParser(); EvaluationContext context = new StandardEvaluationContext(); context.setVariable("variable", "hello1"); context.setVariable("variable", "hello2"); String result1 = parser.parseExpression("#variable").getValue(context, String.class); System.out.println("r1=="+result1); context = new StandardEvaluationContext(12); String result2 = parser.parseExpression("#root-1").getValue(context, String.class); System.out.println("r2=="+result2); String result3 = parser.parseExpression("#this").getValue(context, String.class); System.out.println("r3=="+result3); 輸出結(jié)果: r1==hello2 r2==11 r3==12自定義函數(shù) 目前只支持類靜態(tài)方法注冊(cè)為自定義函數(shù);SpEL使用StandardEvaluationContext的registerFunction方法進(jìn)行注冊(cè)自定義函數(shù),
其實(shí)完全可以使用setVariable代替,兩者其本質(zhì)是一樣的。示例如下:java代碼: ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); Method parseInt = Integer.class.getDeclaredMethod("parseInt", String.class); context.registerFunction("regParseInt", parseInt); context.setVariable("parseInt2", parseInt); String expression1 = "#regParseInt('3') == #parseInt2('3')"; boolean result = parser.parseExpression(expression1).getValue(context, boolean.class); System.out.println("result="+result); 可以看出“registerFunction”和“setVariable”都可以注冊(cè)自定義函數(shù),但是兩個(gè)方法的含義不一樣,推薦使用“registerFunction”方法注冊(cè)自定義函數(shù)。賦值表達(dá)式 SpEL即允許給自定義變量賦值,也允許給跟對(duì)象賦值,直接使用“#variableName=value”即可賦值。示例如下:java代碼:1:parser.parseExpression("#root=‘Hi'").getValue(context, String.class); 2:parser.parseExpression("#this=‘Hi'").getValue(context, String.class); 3:context.setVariable("#variable", "variable"); 對(duì)象屬性存取及安全導(dǎo)航表達(dá)式 對(duì)象屬性獲取非常簡(jiǎn)單,使用如“a.property.property”這種點(diǎn)綴式獲取,SpEL對(duì)于屬性名首字母是不區(qū)分大小寫的; SpEL還引入了Groovy語(yǔ)言中的安全導(dǎo)航運(yùn)算符“(對(duì)象|屬性)?.屬性”,用來(lái)避免當(dāng)“?.”前邊的表達(dá)式為null時(shí)拋出空指針異常,而是返回null; 修改屬性值可以通過(guò)賦值表達(dá)式或Expression接口的setValue方法修改。 示例如下:java代碼:UserModel um = new UserModel(); um.setUuid("User1"); um.setName("UserName1"); ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); context.setVariable("um",um); //取值 Expression expression = parser.parseExpression("'uuid='+#um.uuid + ',name='+#um.name"); String v = expression.getValue(context,String.class); System.out.println("v=="+v); //賦值 expression = parser.parseExpression("'uuid='+(#um.uuid='newUser') + ',name='+#um.name"); v = expression.getValue(context,String.class); System.out.println("v2=="+v); 輸出結(jié)果: v==uuid=User1,name=UserName1 v2==uuid=newUser,name=UserName1 對(duì)象方法調(diào)用 對(duì)象方法調(diào)用更簡(jiǎn)單,跟Java語(yǔ)法一樣;如“‘Hello’.substring(1,3)”將返回“el”;而對(duì)于根對(duì)象可以直接調(diào)用方法。Bean引用 SpEL支持使用“@”符號(hào)來(lái)引用Bean,在引用Bean時(shí)需要使用BeanResolver接口實(shí)現(xiàn)來(lái)查找Bean,Spring提供BeanFactoryResolver實(shí)現(xiàn),示例如下:java代碼:ApplicationContext ctx = new ClassPathXmlApplicationContext( new String[] {"applicationContext.xml"}); ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); context.setBeanResolver(new BeanFactoryResolver(ctx)); String result1 = parser.parseExpression("@myBean.test()").getValue(context, String.class); 內(nèi)聯(lián)List 從Spring3.0.4開始支持內(nèi)聯(lián)List,使用{表達(dá)式,……}定義內(nèi)聯(lián)List,如“{1,2,3}”將返回一個(gè)整型的ArrayList,而“{}”將返回空的List,
對(duì)于字面量表達(dá)式列表,SpEL會(huì)使用java.util.Collections.unmodifiableList方法將列表設(shè)置為不可修改。示例如下:1://將返回不可修改的空List List<Integer> result2 = parser.parseExpression("{}").getValue(List.class); 2:對(duì)于字面量列表也將返回不可修改的List ExpressionParser parser = new SpelExpressionParser(); List<Integer> result1 = parser.parseExpression("{1,2,3}").getValue(List. class); //result1.set(0, 2);//這句話會(huì)報(bào)錯(cuò),因?yàn)閘ist不可以修改 System. out.println(result1); 3://對(duì)于列表中只要有一個(gè)不是字面量表達(dá)式,將只返回原始List, //不會(huì)進(jìn)行不可修改處理,也就是可以修改 String expression3 = "{{1+2,2+4},{3,4+4}}"; List<List<Integer>> result3 = parser.parseExpression(expression3).getValue(List.class); result3.get(0).set(0, 1);內(nèi)聯(lián)數(shù)組 和Java 數(shù)組定義類似,只是在定義時(shí)進(jìn)行多維數(shù)組初始化。 示例如下: 1://定義一維數(shù)組并初始化 int[] result1 = parser.parseExpression("new int[1]").getValue(int[].class); 2://聲明二維數(shù)組并初始化 int[] result2 = parser.parseExpression("new int[2]{1,2}").getValue(int[].class); 3://定義多維數(shù)組但不初始化 int[][][] result3 = parser.parseExpression(expression3).getValue(int[][][].class); 4://錯(cuò)誤的定義多維數(shù)組,多維數(shù)組不能初始化 String expression4 = "new int[1][2][3]{{1}{2}{3}}"; int[][][] result4 = parser.parseExpression(expression4).getValue(int[][][].class);訪問(wèn)元素 SpEL目前支持所有集合類型和字典類型的元素訪問(wèn),使用“集合[索引]”訪問(wèn)集合元素,使用“map[key]”訪問(wèn)字典元素 。示例如下; 1://SpEL內(nèi)聯(lián)List訪問(wèn) int result1 = parser.parseExpression("{1,2,3}[0]").getValue(int.class); //相當(dāng)于result1.get(0)2://SpEL目前支持所有集合類型的訪問(wèn) Collection<Integer> collection = new HashSet<Integer>(); collection.add(1); collection.add(2); EvaluationContext context2 = new StandardEvaluationContext(); context2.setVariable("collection", collection); int result2 = parser.parseExpression("#collection[1]").getValue(context2, int.class);3://SpEL對(duì)Map字典元素訪問(wèn)的支持 Map<String, Integer> map = new HashMap<String, Integer>(); map.put("a", 1); EvaluationContext context3 = new StandardEvaluationContext(); context3.setVariable("map", map); int result3 = parser.parseExpression("#map['a']").getValue(context3, int.class);元素修改 可以使用賦值表達(dá)式或Expression接口的setValue方法修改。示例如下: 1://修改數(shù)組元素值 int[] array = new int[] {1, 2}; EvaluationContext context1 = new StandardEvaluationContext(); context1.setVariable("array", array); int result1 = parser.parseExpression("#array[1] = 3").getValue(context1, int.class); 2://修改集合值 Collection<Integer> collection = new ArrayList<Integer>(); collection.add(1); collection.add(2); EvaluationContext context2 = new StandardEvaluationContext(); context2.setVariable("collection", collection); int result2 = parser.parseExpression("#collection[1] = 3").getValue(context2, int.class); parser.parseExpression("#collection[1]").setValue(context2, 4); result2 = parser.parseExpression("#collection[1]").getValue(context2, int.class); 3://修改map元素值 Map<String, Integer> map = new HashMap<String, Integer>(); map.put("a", 1); EvaluationContext context3 = new StandardEvaluationContext(); context3.setVariable("map", map); int result3 = parser.parseExpression("#map['a'] = 2").getValue(context3, int.class);集合投影 在SQL中投影指從表中選擇出列,而在SpEL指從集合中的元素,通過(guò)選擇來(lái)構(gòu)造新的集合,該集合和原集合具有相同數(shù)量的元素, 但可能屬性不一樣;SpEL使用“(list|map).![投影表達(dá)式]”來(lái)進(jìn)行投影運(yùn)算。 1:示例集合的投影 //1.首先準(zhǔn)備測(cè)試數(shù)據(jù) Collection<UserModel> collection = new ArrayList<UserModel>(); UserModel um1 = new UserModel(); um1.setUuid("u1"); um1.setName("u1Name"); collection.add(um1); UserModel um2 = new UserModel(); um2.setUuid("u2"); um2.setName("u2Name"); collection.add(um2); //2.測(cè)試集合或數(shù)組 EvaluationContext context1 = new StandardEvaluationContext(); ExpressionParser parser = new SpelExpressionParser(); context1.setVariable("collection", collection); Collection<String> result1 = parser.parseExpression(" #collection.![#this.name]").getValue(context1, Collection.class); SpEL投影運(yùn)算還支持Map投影,但Map投影最終只能得到List結(jié)果,對(duì)于投影表達(dá)式中的“#this”將是Map.Entry, 所以可以使用“value”來(lái)獲取值,使用“key”來(lái)獲取鍵。 示例如下: //1.首先準(zhǔn)備測(cè)試數(shù)據(jù) java代碼:UserModel um1 = new UserModel(); um1.setUuid("u1"); um1.setName("u1Name"); UserModel um2 = new UserModel(); um2.setUuid("u2"); um2.setName("u2Name"); Map<String, UserModel> map = new HashMap<String, UserModel>(); map.put(um1.getUuid(),um1); map.put(um2.getUuid(),um2); //2.測(cè)試Map投影 EvaluationContext context1 = new StandardEvaluationContext(); ExpressionParser parser = new SpelExpressionParser(); context1.setVariable("map", map); Collection<String> result1 = parser.parseExpression("#map.![#this.value.name]").getValue(context1, Collection.class); 集合篩選 在SpEL指根據(jù)原集合通過(guò)條件表達(dá)式選擇出滿足條件的元素并構(gòu)造為新的集合,SpEL使用“(list|map).?[選擇表達(dá)式]”,其中選擇表達(dá)式結(jié)果必須是boolean類型,
如果true則選擇的元素將添加到新集合中,false將不添加到新集合中。示例如下: //1:準(zhǔn)備測(cè)試數(shù)據(jù)的過(guò)程跟上一個(gè)示例一樣,就不重復(fù)了 //2.測(cè)試集合或數(shù)組的篩選 java代碼:EvaluationContext context1 = new StandardEvaluationContext(); ExpressionParser parser = new SpelExpressionParser(); context1.setVariable("collection", collection); Collection<String> result1 = parser.parseExpression("#collection.?[#this.uuid.equals('u1')]").getValue(context1, Collection.class); //測(cè)試Map篩選 java代碼:EvaluationContext context1 = new StandardEvaluationContext(); ExpressionParser parser = new SpelExpressionParser(); context1.setVariable("map", map); Map<String,UserModel> result1 = parser.parseExpression("#map.?[#this.key=='u1']").getValue(context1, Map.class); nXml風(fēng)格的配置 SpEL支持在Bean定義時(shí)使用,默認(rèn)使用“#{SpEL表達(dá)式}”表示,不允許嵌套。其中“#root”根對(duì)象默認(rèn)可以認(rèn)為是ApplicationContext,獲取根對(duì)象屬性其實(shí)是獲取容器中的Bean。 nXml風(fēng)格的配置示例----通過(guò)SpEL表達(dá)式設(shè)置值java代碼: <bean id="numberGuess" class="org.spring.samples.NumberGuess"> <property name="randomNumber" value="#{ T(java.lang.Math).random() * 100.0 }"/> </bean> Xml風(fēng)格的配置示例----通過(guò)SpEL表達(dá)式參照其他的Beanjava代碼: <bean id="t1" class="cn.javass.spring3.hello.T2"> <property name="value" value="#{ T(java.lang.Math).random() * 100.0 }"/> </bean> <bean id="t2" class="cn.javass.spring3.hello.T2"> <property name="value" value="#{ T(Double).parseDouble(t1.value) -1 }"></property> </bean> 上面的t1就會(huì)被解析成為參照t1這個(gè)Bean,當(dāng)然也可以使用@t1來(lái)表示。 注解風(fēng)格的配置 使用@Value注解來(lái)指定SpEL表達(dá)式,該注解可以放到字段、方法及方法參數(shù)上。 但是要在配置文件中使用<context:annotation-config/> 來(lái)開啟對(duì)注解的支持。示例如下:java代碼: public class SpELBean { @Value("#{ T(java.lang.Math).random() * 100.0 }") private String value; //setter和getter由于篇幅省略,自己寫上 }
java代碼: public class HelloWorld { public static void main(String[] args) { //構(gòu)造上下文:準(zhǔn)備比如變量定義等等表達(dá)式運(yùn)行需要的上下文數(shù)據(jù) EvaluationContext context = new StandardEvaluationContext(); //創(chuàng)建解析器:提供SpelExpressionParser默認(rèn)實(shí)現(xiàn) ExpressionParser parser = new SpelExpressionParser(); //解析表達(dá)式:使用ExpressionParser來(lái)解析表達(dá)式為相應(yīng)的Expression對(duì)象 Expression expression = parser.parseExpression("('Hello' + ' World').concat(#end)"); //設(shè)置上下文中的變量的值 context.setVariable("end", "!SpringEL"); //執(zhí)行表達(dá)式,獲取運(yùn)行結(jié)果 String str = (String)expression.getValue(context); System.out.println("the str="+str); } } ExpressionParser接口 表示解析器,默認(rèn)實(shí)現(xiàn)是org.springframework.expression.spel.standard包中的SpelExpressionParser類,
使用parseExpression方法將字符串表達(dá)式轉(zhuǎn)換為Expression對(duì)象。 配合 ExpressionParser 接口使用的ParserContext接口用于定義字符串表達(dá)式是不是模板,及模板開始與結(jié)束字符,示例如下:java代碼: public static void main(String[] args) { ExpressionParser parser = new SpelExpressionParser(); //自定義一個(gè)解析模板的規(guī)則 ParserContext parserContext = new ParserContext() { public boolean isTemplate() { return true; } public String getExpressionPrefix() { return "#{"; } public String getExpressionSuffix() { return "}"; } }; String template = "#{'Hello '}#{'World!'}"; Expression expression = parser.parseExpression(template, parserContext); System.out.println( expression.getValue()); } 說(shuō)明 1:在此演示的是使用ParserContext的情況,此處定義了ParserContext實(shí)現(xiàn):定義表達(dá)式是模塊,表達(dá)式前綴為“#{”,后綴為“}”; 2:使用parseExpression解析時(shí)傳入的模板必須以“#{”開頭,以“}”結(jié)尾,如“#{‘Hello ’}#{‘World!’}”。 3:請(qǐng)注意默認(rèn)傳入的字符串表達(dá)式不是模板形式,如之前演示的Hello World。Expression接口 表示表達(dá)式對(duì)象,默認(rèn)實(shí)現(xiàn)是org.springframework.expression.spel.standard包中的SpelExpression,提供getValue方法用于獲取表達(dá)式值,提供setValue方法用于設(shè)置對(duì)象值EvaluationContext接口 表示上下文環(huán)境,默認(rèn)實(shí)現(xiàn)是org.springframework.expression.spel.support包中的StandardEvaluationContext類,使用setRootObject方法來(lái)設(shè)置根對(duì)象,
使用setVariable方法來(lái)注冊(cè)自定義變量,使用registerFunction來(lái)注冊(cè)自定義函數(shù)等等。字面量表達(dá)式:SpEL支持的字面量包括:字符串、數(shù)字類型(int、long、float、double)、布爾類型、null類型 ,示例如下:java代碼:1:String str1 = parser.parseExpression("'Hello World!'").getValue(String.class); 2:String str2 = parser.parseExpression("\"Hello World!\"").getValue(String.class); 3:int int1 = parser.parseExpression("1").getValue(Integer.class); 4:float float1 = parser.parseExpression("1.1").getValue(Float.class); 5:boolean true1 = parser.parseExpression("true").getValue(boolean.class); 6:Object null1 = parser.parseExpression("null").getValue(Object.class); 算數(shù)運(yùn)算表達(dá)式 : SpEL支持加(+)、減(-)、乘(*)、除(/)、求余(%)、冪(^)運(yùn)算,示例如下:1:int result1 = parser.parseExpression("1+2-3*4/2").getValue(Integer.class); 2:int result2 = parser.parseExpression(“4%3”).getValue(Integer.class) ; 3:int result3 = parser.parseExpression("2^3").getValue(Integer.class);SpEL還提供求余(MOD)和除(DIV)運(yùn)算符,與“%”和“/”等價(jià),不區(qū)分大小寫。關(guān)系表達(dá)式 等于(==)、不等于(!=)、大于(>)、大于等于(>=)、小于(<)、小于等于(<=),區(qū)間(between)運(yùn)算,示例如下: 1:“parser.parseExpression(”1>2“).getValue(boolean.class);”將返回false; 2:“parser.parseExpression(”1 between {1, 2}“).getValue(boolean.class);”將返回true。SpEL同樣提供了等價(jià)的“EQ” 、“NE”、 “GT”、“GE”、 “LT” 、“LE”來(lái)表示等于、不等于、大于、大于等于、小于、小于等于,不區(qū)分大小寫邏輯表達(dá)式:且(and)、或(or)、非(!或NOT)。 示例如下: 1:String expression1 = "2>1 and (!true or !false)"; boolean result1 = parser.parseExpression(expression1).getValue(boolean.class); 注意:邏輯運(yùn)算符不支持 Java中的 && 和 ||字符串連接及截取表達(dá)式 使用“+”進(jìn)行字符串連接,使用“‘String’ [index]”來(lái)獲取一個(gè)字符,目前只支持獲取一個(gè)字符, 如“'Hello ' + 'World!'”得到“Hello World!”;而“'Hello World!'[0]”將返回“H”三目運(yùn)算及Elivis運(yùn)算表達(dá)式 1:三目運(yùn)算符 “表達(dá)式1?表達(dá)式2:表達(dá)式3”用于構(gòu)造三目運(yùn)算表達(dá)式,如“2>1?true:false”將返回true; 2:Elivis運(yùn)算符“表達(dá)式1?:表達(dá)式2”從Groovy語(yǔ)言引入,用于簡(jiǎn)化三目運(yùn)算符的,當(dāng)表達(dá)式1為非null時(shí)則返回表達(dá)式1,當(dāng)表達(dá)式1為null時(shí)則返回表達(dá)式2,如“null?:false”將返回false,而“true?:false”將返回true;正則表達(dá)式 使用“str matches regex,如“‘123’ matches ‘\\d{3}’”將返回true;括號(hào)優(yōu)先級(jí)表達(dá)式 使用“(表達(dá)式)”構(gòu)造,括號(hào)里的具有高優(yōu)先級(jí)。類類型表達(dá)式 使用“T(Type)”來(lái)表示java.lang.Class實(shí)例,“Type”必須是類全限定名,“java.lang”包除外,即該包下的類可以不指定包名;
使用類類型表達(dá)式還可以進(jìn)行訪問(wèn)類靜態(tài)方法及類靜態(tài)字段。 示例如下: 1:訪問(wèn)java.lang包的類 Class<String> result1 = parser.parseExpression("T(String)").getValue(Class.class); 2:訪問(wèn)其他包下的類 : String expression2 = "T(cn.javass.spring.chapter5.SpELTest)";Class<String> result2 = parser.parseExpression(expression2).getValue(Class.class); 3:訪問(wèn)類的靜態(tài)字段 int result3=parser.parseExpression("T(Integer).MAX_VALUE").getValue(int.class); 4:訪問(wèn)類的靜態(tài)方法 int result4 = parser.parseExpression("T(Integer).parseInt('1')").getValue(int.class); 類實(shí)例化 類實(shí)例化同樣使用java關(guān)鍵字“new”,類名必須是全限定名,但java.lang包內(nèi)的類型除外,如String、Integer。示例如下: 1:String result1 = parser.parseExpression("new String('hello')").getValue(String.class); 2:Date result2 = parser.parseExpression("new java.util.Date()").getValue(Date.class);instanceof表達(dá)式 SpEL支持instanceof運(yùn)算符,跟Java內(nèi)使用同義;如“hello‘ instanceof T(String)”將返回true。變量定義及引用 1:變量通過(guò)EvaluationContext接口的setVariable(variableName, value)方法定義 2:在表達(dá)式中使用“#variableName”引用; 3:除了引用自定義變量,SpE還允許引用根對(duì)象及當(dāng)前上下文對(duì)象,使用“#root”引用根對(duì)象,使用“#this”引用當(dāng)前上下文對(duì)象; 示例如下:java代碼:ExpressionParser parser = new SpelExpressionParser(); EvaluationContext context = new StandardEvaluationContext(); context.setVariable("variable", "hello1"); context.setVariable("variable", "hello2"); String result1 = parser.parseExpression("#variable").getValue(context, String.class); System.out.println("r1=="+result1); context = new StandardEvaluationContext(12); String result2 = parser.parseExpression("#root-1").getValue(context, String.class); System.out.println("r2=="+result2); String result3 = parser.parseExpression("#this").getValue(context, String.class); System.out.println("r3=="+result3); 輸出結(jié)果: r1==hello2 r2==11 r3==12自定義函數(shù) 目前只支持類靜態(tài)方法注冊(cè)為自定義函數(shù);SpEL使用StandardEvaluationContext的registerFunction方法進(jìn)行注冊(cè)自定義函數(shù),
其實(shí)完全可以使用setVariable代替,兩者其本質(zhì)是一樣的。示例如下:java代碼: ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); Method parseInt = Integer.class.getDeclaredMethod("parseInt", String.class); context.registerFunction("regParseInt", parseInt); context.setVariable("parseInt2", parseInt); String expression1 = "#regParseInt('3') == #parseInt2('3')"; boolean result = parser.parseExpression(expression1).getValue(context, boolean.class); System.out.println("result="+result); 可以看出“registerFunction”和“setVariable”都可以注冊(cè)自定義函數(shù),但是兩個(gè)方法的含義不一樣,推薦使用“registerFunction”方法注冊(cè)自定義函數(shù)。賦值表達(dá)式 SpEL即允許給自定義變量賦值,也允許給跟對(duì)象賦值,直接使用“#variableName=value”即可賦值。示例如下:java代碼:1:parser.parseExpression("#root=‘Hi'").getValue(context, String.class); 2:parser.parseExpression("#this=‘Hi'").getValue(context, String.class); 3:context.setVariable("#variable", "variable"); 對(duì)象屬性存取及安全導(dǎo)航表達(dá)式 對(duì)象屬性獲取非常簡(jiǎn)單,使用如“a.property.property”這種點(diǎn)綴式獲取,SpEL對(duì)于屬性名首字母是不區(qū)分大小寫的; SpEL還引入了Groovy語(yǔ)言中的安全導(dǎo)航運(yùn)算符“(對(duì)象|屬性)?.屬性”,用來(lái)避免當(dāng)“?.”前邊的表達(dá)式為null時(shí)拋出空指針異常,而是返回null; 修改屬性值可以通過(guò)賦值表達(dá)式或Expression接口的setValue方法修改。 示例如下:java代碼:UserModel um = new UserModel(); um.setUuid("User1"); um.setName("UserName1"); ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); context.setVariable("um",um); //取值 Expression expression = parser.parseExpression("'uuid='+#um.uuid + ',name='+#um.name"); String v = expression.getValue(context,String.class); System.out.println("v=="+v); //賦值 expression = parser.parseExpression("'uuid='+(#um.uuid='newUser') + ',name='+#um.name"); v = expression.getValue(context,String.class); System.out.println("v2=="+v); 輸出結(jié)果: v==uuid=User1,name=UserName1 v2==uuid=newUser,name=UserName1 對(duì)象方法調(diào)用 對(duì)象方法調(diào)用更簡(jiǎn)單,跟Java語(yǔ)法一樣;如“‘Hello’.substring(1,3)”將返回“el”;而對(duì)于根對(duì)象可以直接調(diào)用方法。Bean引用 SpEL支持使用“@”符號(hào)來(lái)引用Bean,在引用Bean時(shí)需要使用BeanResolver接口實(shí)現(xiàn)來(lái)查找Bean,Spring提供BeanFactoryResolver實(shí)現(xiàn),示例如下:java代碼:ApplicationContext ctx = new ClassPathXmlApplicationContext( new String[] {"applicationContext.xml"}); ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); context.setBeanResolver(new BeanFactoryResolver(ctx)); String result1 = parser.parseExpression("@myBean.test()").getValue(context, String.class); 內(nèi)聯(lián)List 從Spring3.0.4開始支持內(nèi)聯(lián)List,使用{表達(dá)式,……}定義內(nèi)聯(lián)List,如“{1,2,3}”將返回一個(gè)整型的ArrayList,而“{}”將返回空的List,
對(duì)于字面量表達(dá)式列表,SpEL會(huì)使用java.util.Collections.unmodifiableList方法將列表設(shè)置為不可修改。示例如下:1://將返回不可修改的空List List<Integer> result2 = parser.parseExpression("{}").getValue(List.class); 2:對(duì)于字面量列表也將返回不可修改的List ExpressionParser parser = new SpelExpressionParser(); List<Integer> result1 = parser.parseExpression("{1,2,3}").getValue(List. class); //result1.set(0, 2);//這句話會(huì)報(bào)錯(cuò),因?yàn)閘ist不可以修改 System. out.println(result1); 3://對(duì)于列表中只要有一個(gè)不是字面量表達(dá)式,將只返回原始List, //不會(huì)進(jìn)行不可修改處理,也就是可以修改 String expression3 = "{{1+2,2+4},{3,4+4}}"; List<List<Integer>> result3 = parser.parseExpression(expression3).getValue(List.class); result3.get(0).set(0, 1);內(nèi)聯(lián)數(shù)組 和Java 數(shù)組定義類似,只是在定義時(shí)進(jìn)行多維數(shù)組初始化。 示例如下: 1://定義一維數(shù)組并初始化 int[] result1 = parser.parseExpression("new int[1]").getValue(int[].class); 2://聲明二維數(shù)組并初始化 int[] result2 = parser.parseExpression("new int[2]{1,2}").getValue(int[].class); 3://定義多維數(shù)組但不初始化 int[][][] result3 = parser.parseExpression(expression3).getValue(int[][][].class); 4://錯(cuò)誤的定義多維數(shù)組,多維數(shù)組不能初始化 String expression4 = "new int[1][2][3]{{1}{2}{3}}"; int[][][] result4 = parser.parseExpression(expression4).getValue(int[][][].class);訪問(wèn)元素 SpEL目前支持所有集合類型和字典類型的元素訪問(wèn),使用“集合[索引]”訪問(wèn)集合元素,使用“map[key]”訪問(wèn)字典元素 。示例如下; 1://SpEL內(nèi)聯(lián)List訪問(wèn) int result1 = parser.parseExpression("{1,2,3}[0]").getValue(int.class); //相當(dāng)于result1.get(0)2://SpEL目前支持所有集合類型的訪問(wèn) Collection<Integer> collection = new HashSet<Integer>(); collection.add(1); collection.add(2); EvaluationContext context2 = new StandardEvaluationContext(); context2.setVariable("collection", collection); int result2 = parser.parseExpression("#collection[1]").getValue(context2, int.class);3://SpEL對(duì)Map字典元素訪問(wèn)的支持 Map<String, Integer> map = new HashMap<String, Integer>(); map.put("a", 1); EvaluationContext context3 = new StandardEvaluationContext(); context3.setVariable("map", map); int result3 = parser.parseExpression("#map['a']").getValue(context3, int.class);元素修改 可以使用賦值表達(dá)式或Expression接口的setValue方法修改。示例如下: 1://修改數(shù)組元素值 int[] array = new int[] {1, 2}; EvaluationContext context1 = new StandardEvaluationContext(); context1.setVariable("array", array); int result1 = parser.parseExpression("#array[1] = 3").getValue(context1, int.class); 2://修改集合值 Collection<Integer> collection = new ArrayList<Integer>(); collection.add(1); collection.add(2); EvaluationContext context2 = new StandardEvaluationContext(); context2.setVariable("collection", collection); int result2 = parser.parseExpression("#collection[1] = 3").getValue(context2, int.class); parser.parseExpression("#collection[1]").setValue(context2, 4); result2 = parser.parseExpression("#collection[1]").getValue(context2, int.class); 3://修改map元素值 Map<String, Integer> map = new HashMap<String, Integer>(); map.put("a", 1); EvaluationContext context3 = new StandardEvaluationContext(); context3.setVariable("map", map); int result3 = parser.parseExpression("#map['a'] = 2").getValue(context3, int.class);集合投影 在SQL中投影指從表中選擇出列,而在SpEL指從集合中的元素,通過(guò)選擇來(lái)構(gòu)造新的集合,該集合和原集合具有相同數(shù)量的元素, 但可能屬性不一樣;SpEL使用“(list|map).![投影表達(dá)式]”來(lái)進(jìn)行投影運(yùn)算。 1:示例集合的投影 //1.首先準(zhǔn)備測(cè)試數(shù)據(jù) Collection<UserModel> collection = new ArrayList<UserModel>(); UserModel um1 = new UserModel(); um1.setUuid("u1"); um1.setName("u1Name"); collection.add(um1); UserModel um2 = new UserModel(); um2.setUuid("u2"); um2.setName("u2Name"); collection.add(um2); //2.測(cè)試集合或數(shù)組 EvaluationContext context1 = new StandardEvaluationContext(); ExpressionParser parser = new SpelExpressionParser(); context1.setVariable("collection", collection); Collection<String> result1 = parser.parseExpression(" #collection.![#this.name]").getValue(context1, Collection.class); SpEL投影運(yùn)算還支持Map投影,但Map投影最終只能得到List結(jié)果,對(duì)于投影表達(dá)式中的“#this”將是Map.Entry, 所以可以使用“value”來(lái)獲取值,使用“key”來(lái)獲取鍵。 示例如下: //1.首先準(zhǔn)備測(cè)試數(shù)據(jù) java代碼:UserModel um1 = new UserModel(); um1.setUuid("u1"); um1.setName("u1Name"); UserModel um2 = new UserModel(); um2.setUuid("u2"); um2.setName("u2Name"); Map<String, UserModel> map = new HashMap<String, UserModel>(); map.put(um1.getUuid(),um1); map.put(um2.getUuid(),um2); //2.測(cè)試Map投影 EvaluationContext context1 = new StandardEvaluationContext(); ExpressionParser parser = new SpelExpressionParser(); context1.setVariable("map", map); Collection<String> result1 = parser.parseExpression("#map.![#this.value.name]").getValue(context1, Collection.class); 集合篩選 在SpEL指根據(jù)原集合通過(guò)條件表達(dá)式選擇出滿足條件的元素并構(gòu)造為新的集合,SpEL使用“(list|map).?[選擇表達(dá)式]”,其中選擇表達(dá)式結(jié)果必須是boolean類型,
如果true則選擇的元素將添加到新集合中,false將不添加到新集合中。示例如下: //1:準(zhǔn)備測(cè)試數(shù)據(jù)的過(guò)程跟上一個(gè)示例一樣,就不重復(fù)了 //2.測(cè)試集合或數(shù)組的篩選 java代碼:EvaluationContext context1 = new StandardEvaluationContext(); ExpressionParser parser = new SpelExpressionParser(); context1.setVariable("collection", collection); Collection<String> result1 = parser.parseExpression("#collection.?[#this.uuid.equals('u1')]").getValue(context1, Collection.class); //測(cè)試Map篩選 java代碼:EvaluationContext context1 = new StandardEvaluationContext(); ExpressionParser parser = new SpelExpressionParser(); context1.setVariable("map", map); Map<String,UserModel> result1 = parser.parseExpression("#map.?[#this.key=='u1']").getValue(context1, Map.class); nXml風(fēng)格的配置 SpEL支持在Bean定義時(shí)使用,默認(rèn)使用“#{SpEL表達(dá)式}”表示,不允許嵌套。其中“#root”根對(duì)象默認(rèn)可以認(rèn)為是ApplicationContext,獲取根對(duì)象屬性其實(shí)是獲取容器中的Bean。 nXml風(fēng)格的配置示例----通過(guò)SpEL表達(dá)式設(shè)置值java代碼: <bean id="numberGuess" class="org.spring.samples.NumberGuess"> <property name="randomNumber" value="#{ T(java.lang.Math).random() * 100.0 }"/> </bean> Xml風(fēng)格的配置示例----通過(guò)SpEL表達(dá)式參照其他的Beanjava代碼: <bean id="t1" class="cn.javass.spring3.hello.T2"> <property name="value" value="#{ T(java.lang.Math).random() * 100.0 }"/> </bean> <bean id="t2" class="cn.javass.spring3.hello.T2"> <property name="value" value="#{ T(Double).parseDouble(t1.value) -1 }"></property> </bean> 上面的t1就會(huì)被解析成為參照t1這個(gè)Bean,當(dāng)然也可以使用@t1來(lái)表示。 注解風(fēng)格的配置 使用@Value注解來(lái)指定SpEL表達(dá)式,該注解可以放到字段、方法及方法參數(shù)上。 但是要在配置文件中使用<context:annotation-config/> 來(lái)開啟對(duì)注解的支持。示例如下:java代碼: public class SpELBean { @Value("#{ T(java.lang.Math).random() * 100.0 }") private String value; //setter和getter由于篇幅省略,自己寫上 }
?
轉(zhuǎn)載于:https://www.cnblogs.com/rinack/p/7885511.html
總結(jié)
以上是生活随笔為你收集整理的Spring3的表达式语言的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: libpcap抓取数据包
- 下一篇: JavaScript---事件详解