import java.lang.reflect.Method; import org.springframework.expression.EvaluationContext; import org.springframework.expression.Expression; import org.springframework.expression.ExpressionParser; import org.springframework.expression.ParserContext; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; public class StudySpEL { public static void main(String[] args) { getStart(); parseContext(); regFunction(); } public static void getStart() { //待解析的字符串,注意整個字符串是要解析的,若是要解析的字符串中包含 //字符串要使用單引號,例如要寫成下面toParseString的樣子而不是 //"welcome to el world + #name"這樣,由於不加引號,解析器 //就會把它當作字段或者屬性來解析,而沒有這個屬性或者字段就會出錯 final String toParseString = "'welcome to el world' + #name"; //解析器,spring爲咱們提供了一個SpelExpressionParser解析器 ExpressionParser parser = new SpelExpressionParser(); //用解析器把待解析的字符串解析爲表達式Expression //Expression的結構就是一些AST節點,例如:"'welcome to el world' + #name"字符串 //就被拆分爲welcome to el wolrd #name這樣的節點,方便被EvaluationContext計算 Expression expression = parser.parseExpression(toParseString); //EvaluationContext就是計算的上下文,用來替換Expression中的變量表達式的 //例以下面就是把待解析字符串(上下文)中的name變量替換爲everybody EvaluationContext context = new StandardEvaluationContext(); context.setVariable("name", "everybody"); Object result = expression.getValue(context); System.out.println(result); } /** * 想spring中就會發現有 @Value("#{T(Math).PI * 4^2}") 這樣的註解 * 它的待解析的字符串是#{}這樣的形式,怎麼辦,spring還有一個解析的上下文接口 * ParserContext 它提供了一個默認的實現ParserContext.TEMPLATE_EXPRESSION * 就是解析以#{開頭以}結束的字符串,固然也能夠本身實現ParserContext接口 */ public static void parseContext() { //SpEL 支持+ - * / ^ % 等運算 //SpEL 支持類型表達式 要求除了java.lang包之外的類使用類的全限定名稱 //T(Math).PI 就是訪問java.lang.Math 的靜態字段PI final String toParseString = "#{T(Math).PI * 4^2}"; ExpressionParser parser = new SpelExpressionParser(); //由於待解析字符串是#{}這樣的形式因此使用ParserContext上下文,ParserContext.TEMPLATE_EXPRESSION Expression expression = parser.parseExpression(toParseString, ParserContext.TEMPLATE_EXPRESSION); Object value = expression.getValue(); //PI*16 System.out.println(value); } /** * SpEL支持自定義函數,只能是靜態方法 */ public static void regFunction() { final String toParseString = "#customerFunction(4,6)"; ExpressionParser parser = new SpelExpressionParser(); Expression expression = parser.parseExpression(toParseString); StandardEvaluationContext context = new StandardEvaluationContext(); Method customerFuction = null; try { customerFuction = StudySpEL.class.getDeclaredMethod("customerFunction", int.class,int.class); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } //StandardEvaluationContext 纔有registerFunction方法,也能夠使用setVariable //註冊方法 context.registerFunction("customerFunction", customerFuction); Integer value = expression.getValue(context, int.class); System.out.println(value); } public static int customerFunction(int a,int b) { return a+b; } }
雖然咱們平時可能不多用到很複雜的表達式,想解析mybatis的Mapper文件這種級別的,可是咱們能夠在註解上使用表達式,能夠讓註解有更多的動態特性,在結合aop,能夠把一些實現作的很優雅。因此瞭解一點spring的EL老是沒有壞處的。
java