文章目錄
- spel底層
- spel核心代碼
- TokenKind源碼
- spel本地調試
- spel示例
- spel list例子
- spel 對象例子
- spel list例子
- SimpleEvaluationContext 類找不到
- ##### spel 如何表示包含(也就是like)?
- spel官網文檔
- ognl表達式
- ognl和表達式語言的區別
這里重點說下SPEL(Spring Expression Language)。
spel底層
還是那句話,沒有誰想要研究底層,除非他遇到問題解不了。
個人就是這種情況,如:spel模糊匹配怎么弄?
文檔中的例子不一定全,簡單說就是比較概括,但是底層代碼卻是最完整的。
什么?看代碼太麻煩。恰恰相反,最復雜的就是最簡單的,看了看代碼,反而對spel的了解深入了些。
spel核心代碼
核心代碼在這里(表達式非模板,模板有另外的解析):
org.springframework.expression.spel.standard.InternalSpelExpressionParser.eatExpression()
它的機制比較清楚。簡單說就是根據符號,進行解析。
TokenKind源碼
這個枚舉類很關鍵,所有的表達式符號都在這里,所以不用去查是否支持了,看這個類就一目了然。
照搬源碼:
enum TokenKind {// ordered by priority - operands firstLITERAL_INT,LITERAL_LONG,LITERAL_HEXINT,LITERAL_HEXLONG,LITERAL_STRING,LITERAL_REAL,LITERAL_REAL_FLOAT,LPAREN("("),RPAREN(")"),COMMA(","),IDENTIFIER,COLON(":"),HASH("#"),RSQUARE("]"),LSQUARE("["),LCURLY("{"),RCURLY("}"),DOT("."),PLUS("+"),STAR("*"),MINUS("-"),SELECT_FIRST("^["),SELECT_LAST("$["),QMARK("?"),PROJECT("!["),DIV("/"),GE(">="),GT(">"),LE("<="),LT("<"),EQ("=="),NE("!="),MOD("%"),NOT("!"),ASSIGN("="),INSTANCEOF("instanceof"),MATCHES("matches"),BETWEEN("between"),SELECT("?["),POWER("^"),ELVIS("?:"),SAFE_NAVI("?."),BEAN_REF("@"),FACTORY_BEAN_REF("&"),SYMBOLIC_OR("||"),SYMBOLIC_AND("&&"),INC("++"),DEC("--");final char[] tokenChars;final private boolean hasPayload; // is there more to this token than simply the kindprivate TokenKind(String tokenString) {this.tokenChars = tokenString.toCharArray();this.hasPayload = (this.tokenChars.length == 0);}private TokenKind() {this("");}@Overridepublic String toString() {return (name() + (this.tokenChars.length !=0 ? "(" + new String(this.tokenChars) +")" : ""));}public boolean hasPayload() {return this.hasPayload;}public int getLength() {return this.tokenChars.length;}}
spel本地調試
通過屬性注入的方式也不慢,但是還有更簡單的方式,就是本地直接調試,如在main方法里面。
不只一種方式可以配置環境變量,如:
1、StandardEvaluationContext
StandardEvaluationContext context = new StandardEvaluationContext();
2、EvaluationContext context(需要spring 4.3.15.RELEASE及以上)
EvaluationContext context = StandardEvaluationContext.forReadOnlyDataBinding().build();
后續示例,context哪個都可能啊。
spel示例
spel list例子
List<Integer> primes = new ArrayList<Integer>();
primes.addAll(Arrays.asList(2,3,5,7,11,13,17));
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
context.setVariable("primes",primes);
List<Integer> primesGreaterThanTen = (List<Integer>) parser.parseExpression("#primes.?[#this>10]").getValue(context);
System.out.println(JSON.toJSONString(primesGreaterThanTen));
spel 對象例子
String usernmae =
(String) parser.parseExpression("#user.userName").getValue(context);
System.out.println(usernmae);
spel list例子
List primes = new ArrayList();
primes.addAll(Arrays.asList(2,3,5,7,11,13,17));
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
context.setVariable(“primes”,primes);
List primesGreaterThanTen = (List) parser.parseExpression(“#primes.?[#this>10]”).getValue(context);
System.out.println(JSON.toJSONString(primesGreaterThanTen));
SimpleEvaluationContext 類找不到
SimpleEvaluationContext was added in 4.3.15.RELEASE so the fact you can’t find it in 4.3.14.RELEASE is perfectly normal.
Spring Boot 1.5.13 uses Spring Framework 4.3.17.RELEASE.
由此可見,由于SimpleEvaluationContext 是4.3.15.RELEASE才增加的,只要把依賴的版本大于這個版本就行了。但由于官方推薦springBoot 1.5.13應該使用spring的4.3.17.RELEASE版本,那就把spring版本升級。
簡單說,就是SimpleEvaluationContext是4.3.15.RELEASE及以上版本才支持的。
升級下maven即可。
注:spring版本和release版本不是一回事。
##### spel 如何表示包含(也就是like)?
待辦
spel官網文檔
這里用5.3.18版本的吧,如下連接直接定位到spel。
https://docs.spring.io/spring-framework/docs/5.3.18/reference/html/core.html#expressions
ognl表達式
ognl表達式我們一定不陌生,可能會說沒聽說過,實際我們一直在用。
舉個最簡單的例子,spring的配置文件,其實就是ognl表達式。
spring.application.name=crm
server.port=8080
為什么要整理下呢?是因為遇到個問題,需要模糊匹配個值,居然不知道如何寫,難道真的啥也不會了?
ognl和表達式語言的區別
ognl最早出現在structs,需要和structs一起使用。
表達式語言則是個比較廣泛的概念,其中最出名的就是spring的(是spring的嗎?)el表達式。