# 【第五章】Spring表達式語言 之 5.1 概述 5.2 SpEL基礎 ——跟我學spring3
## 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語法了。
- 跟我學 Spring3
- 【第二章】 IoC 之 2.1 IoC基礎 ——跟我學Spring3
- 【第二章】 IoC 之 2.2 IoC 容器基本原理 ——跟我學Spring3
- 【第二章】 IoC 之 2.3 IoC的配置使用——跟我學Spring3
- 【第三章】 DI 之 3.1 DI的配置使用 ——跟我學spring3
- 【第三章】 DI 之 3.2 循環依賴 ——跟我學spring3
- 【第三章】 DI 之 3.3 更多DI的知識 ——跟我學spring3
- 【第三章】 DI 之 3.4 Bean的作用域 ——跟我學spring3
- 【第四章】 資源 之 4.1 基礎知識 ——跟我學spring3
- 【第四章】 資源 之 4.2 內置Resource實現 ——跟我學spring3
- 【第四章】 資源 之 4.3 訪問Resource ——跟我學spring3
- 【第四章】 資源 之 4.4 Resource通配符路徑 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.1 概述 5.2 SpEL基礎 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.3 SpEL語法 ——跟我學spring3
- 【第五章】Spring表達式語言 之 5.4在Bean定義中使用EL—跟我學spring3
- 【第六章】 AOP 之 6.1 AOP基礎 ——跟我學spring3
- 【第六章】 AOP 之 6.2 AOP的HelloWorld ——跟我學spring3
- 【第六章】 AOP 之 6.3 基于Schema的AOP ——跟我學spring3
- 【第六章】 AOP 之 6.4 基于@AspectJ的AOP ——跟我學spring3
- 【第六章】 AOP 之 6.5 AspectJ切入點語法詳解 ——跟我學spring3
- 【第六章】 AOP 之 6.6 通知參數 ——跟我學spring3
- 【第六章】 AOP 之 6.7 通知順序 ——跟我學spring3
- 【第六章】 AOP 之 6.8 切面實例化模型 ——跟我學spring3
- 【第六章】 AOP 之 6.9 代理機制 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.1 概述 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.2 JDBC模板類 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.3 關系數據庫操作對象化 ——跟我學spring3
- 【第七章】 對JDBC的支持 之 7.4 Spring提供的其它幫助 ——跟我學spring3【私塾在線原創】
- 【第七章】 對JDBC的支持 之 7.5 集成Spring JDBC及最佳實踐 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.1 概述 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.2 集成Hibernate3 ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.3 集成iBATIS ——跟我學spring3
- 【第八章】 對ORM的支持 之 8.4 集成JPA ——跟我學spring3
- 【第九章】 Spring的事務 之 9.1 數據庫事務概述 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.2 事務管理器 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.3 編程式事務 ——跟我學spring3
- 【第九章】 Spring的事務 之 9.4 聲明式事務 ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.1 概述 ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.2 集成Struts1.x ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.3 集成Struts2.x ——跟我學spring3
- 【第十章】集成其它Web框架 之 10.4 集成JSF ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.1 概述 ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.2 實現通用層 ——跟我學spring3
- 【第十一章】 SSH集成開發積分商城 之 11.3 實現積分商城層 ——跟我學spring3
- 【第十二章】零配置 之 12.1 概述 ——跟我學spring3
- 【第十二章】零配置 之 12.2 注解實現Bean依賴注入 ——跟我學spring3
- 【第十二章】零配置 之 12.3 注解實現Bean定義 ——跟我學spring3
- 【第十二章】零配置 之 12.4 基于Java類定義Bean配置元數據 ——跟我學spring3
- 【第十二章】零配置 之 12.5 綜合示例-積分商城 ——跟我學spring3
- 【第十三章】 測試 之 13.1 概述 13.2 單元測試 ——跟我學spring3
- 【第十三章】 測試 之 13.3 集成測試 ——跟我學spring3
- 跟我學 Spring MVC
- SpringMVC + spring3.1.1 + hibernate4.1.0 集成及常見問題總結
- Spring Web MVC中的頁面緩存支持 ——跟我學SpringMVC系列
- Spring3 Web MVC下的數據類型轉換(第一篇)——《跟我學Spring3 Web MVC》搶先看
- Spring3 Web MVC下的數據格式化(第二篇)——《跟我學Spring3 Web MVC》搶先看
- 第一章 Web MVC簡介 —— 跟開濤學SpringMVC
- 第二章 Spring MVC入門 —— 跟開濤學SpringMVC
- 第三章 DispatcherServlet詳解 ——跟開濤學SpringMVC
- 第四章 Controller接口控制器詳解(1)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(2)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(3)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解 (4)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(5)——跟著開濤學SpringMVC
- 跟著開濤學SpringMVC 第一章源代碼下載
- 第二章 Spring MVC入門 源代碼下載
- 第四章 Controller接口控制器詳解 源代碼下載
- 第四章 Controller接口控制器詳解(6)——跟著開濤學SpringMVC
- 第四章 Controller接口控制器詳解(7 完)——跟著開濤學SpringMVC
- 第五章 處理器攔截器詳解——跟著開濤學SpringMVC
- 源代碼下載 第五章 處理器攔截器詳解——跟著開濤學SpringMVC
- 注解式控制器運行流程及處理器定義 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- 源代碼下載 第六章 注解式控制器詳解
- SpringMVC3強大的請求映射規則詳解 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- Spring MVC 3.1新特性 生產者、消費者請求限定 —— 第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC強大的數據綁定(1)——第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC強大的數據綁定(2)——第六章 注解式控制器詳解——跟著開濤學SpringMVC
- SpringMVC數據類型轉換——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC
- SpringMVC數據格式化——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC
- SpringMVC數據驗證——第七章 注解式控制器的數據驗證、類型轉換及格式化——跟著開濤學SpringMVC