文章目录
- 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表达式。