5.1 ?? 概述
5.1.1? 概述
?????? Spring表達式語言全稱為“Spring Expression Language”,縮寫為“SpEL”,類似于Struts2x中使用的OGNL表達式語言,能在運行時構建復雜表達式、存取對象圖屬性、對象方法調用等等,并且能與Spring功能完美整合,如能用來配置Bean定義。
?????? 表達式語言給靜態Java語言增加了動態功能。
?????? SpEL是單獨模塊,只依賴于core模塊,不依賴于其他模塊,可以單獨使用。
5.1.2? 能干什么
?????? 表達式語言一般是用最簡單的形式完成最主要的工作,減少我們的工作量。
?????? SpEL支持如下表達式:
一、基本表達式: 字面量表達式、關系,邏輯與算數運算表達式、字符串連接及截取表達式、三目運算及Elivis表達式、正則表達式、括號優先級表達式;
二、類相關表達式: 類類型表達式、類實例化、instanceof表達式、變量定義及引用、賦值表達式、自定義函數、對象屬性存取及安全導航表達式、對象方法調用、Bean引用;
三、集合相關表達式: 內聯List、內聯數組、集合,字典訪問、列表,字典,數組修改、集合投影、集合選擇;不支持多維內聯數組初始化;不支持內聯字典定義;
四、其他表達式 :模板表達式。
注:SpEL 表達式中的關鍵字是不區分大小寫的。
5.2? SpEL基礎
5.2.1? HelloWorld
?????? 首先準備支持SpEL的Jar包:“org.springframework.expression-3.0.5.RELEASE.jar”將其添加到類路徑中。
?????? SpEL在求表達式值時一般分為四步,其中第三步可選:首先構造一個解析器,其次解析器解析字符串表達式,在此構造上下文,最后根據上下文得到表達式運算后的值。
?????? 讓我們看下代碼片段吧:
?
?
package cn.javass.spring.chapter5;
import junit.framework.Assert;
import org.junit.Test;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
public class SpELTest {
@Test
public void helloWorld() {
ExpressionParser parser = new SpelExpressionParser();
Expression expression =
parser.parseExpression("('Hello' + ' World').concat(#end)");
EvaluationContext context = new StandardEvaluationContext();
context.setVariable("end", "!");
Assert.assertEquals("Hello World!", expression.getValue(context));
}
}
?
接下來讓我們分析下代碼:
1)創建解析器:SpEL使用ExpressionParser接口表示解析器,提供SpelExpressionParser默認實現;
2)解析表達式:使用ExpressionParser的parseExpression來解析相應的表達式為Expression對象。
3)構造上下文:準備比如變量定義等等表達式需要的上下文數據。
4)求值:通過Expression接口的getValue方法根據上下文獲得表達式值。
?
是不是很簡單,接下來讓我們看下其具體實現及原理吧。
5.2.3? SpEL原理及接口
?????? SpEL提供簡單的接口從而簡化用戶使用,在介紹原理前讓我們學習下幾個概念:
??????? 一、表達式: 表達式是表達式語言的核心,所以表達式語言都是圍繞表達式進行的,從我們角度來看是“干什么”;
??????? 二、解析器: 用于將字符串表達式解析為表達式對象,從我們角度來看是“誰來干”;
??????? 三、上下文: 表達式對象執行的環境,該環境可能定義變量、定義自定義函數、提供類型轉換等等,從我們角度看是“在哪干”;
??????? 四、根對象及活動上下文對象: 根對象是默認的活動上下文對象,活動上下文對象表示了當前表達式操作的對象,從我們角度看是“對誰干”。
?????? 理解了這些概念后,讓我們看下SpEL如何工作的呢,如圖5-1所示:
圖5-1 工作原理
?????? 1)首先定義表達式:“1+2”;
?????? 2)定義解析器ExpressionParser實現,SpEL提供默認實現SpelExpressionParser;
?????? 2.1)SpelExpressionParser解析器內部使用Tokenizer類進行詞法分析,即把字符串流分析為記號流,記號在SpEL使用Token類來表示;
?????? 2.2)有了記號流后,解析器便可根據記號流生成內部抽象語法樹;在SpEL中語法樹節點由SpelNode接口實現代表:如OpPlus表示加操作節點、IntLiteral表示int型字面量節點;使用SpelNodel實現組成了抽象語法樹;
?????? 2.3)對外提供Expression接口來簡化表示抽象語法樹,從而隱藏內部實現細節,并提供getValue簡單方法用于獲取表達式值;SpEL提供默認實現為SpelExpression;
?????? 3)定義表達式上下文對象(可選),SpEL使用EvaluationContext接口表示上下文對象,用于設置根對象、自定義變量、自定義函數、類型轉換器等,SpEL提供默認實現StandardEvaluationContext;
4)使用表達式對象根據上下文對象(可選)求值(調用表達式對象的getValue方法)獲得結果。
接下來讓我們看下SpEL的主要接口吧:
1 )ExpressionParser 接口 :表示解析器,默認實現是org.springframework.expression.spel.standard包中的SpelExpressionParser類,使用parseExpression方法將字符串表達式轉換為Expression對象,對于ParserContext接口用于定義字符串表達式是不是模板,及模板開始與結束字符:
?
public interface ExpressionParser {
Expression parseExpression(String expressionString);
Expression parseExpression(String expressionString, ParserContext context);
}
?
?
來看下示例:
?
@Test
public void testParserContext() {
ExpressionParser parser = new SpelExpressionParser();
ParserContext parserContext = new ParserContext() {
@Override
public boolean isTemplate() {
return true;
}
@Override
public String getExpressionPrefix() {
return "#{";
}
@Override
public String getExpressionSuffix() {
return "}";
}
};
String template = "#{'Hello '}#{'World!'}";
Expression expression = parser.parseExpression(template, parserContext);
Assert.assertEquals("Hello World!", expression.getValue());
}
?
?
在此我們演示的是使用ParserContext的情況,此處定義了ParserContext實現:定義表達式是模塊,表達式前綴為“#{”,后綴為“}”;使用parseExpression解析時傳入的模板必須以“#{”開頭,以“}”結尾,如"#{'Hello '}#{'World!'}"。
默認傳入的字符串表達式不是模板形式,如之前演示的Hello World。
?
2 )EvaluationContext 接口 :表示上下文環境,默認實現是org.springframework.expression.spel.support包中的StandardEvaluationContext類,使用setRootObject方法來設置根對象,使用setVariable方法來注冊自定義變量,使用registerFunction來注冊自定義函數等等。
?
3 )Expression 接口: 表示表達式對象,默認實現是org.springframework.expression.spel.standard包中的SpelExpression,提供getValue方法用于獲取表達式值,提供setValue方法用于設置對象值。
了解了SpEL原理及接口,接下來的事情就是SpEL語法了。
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

