这是我参与8月更文挑战的第3天,活动详情查看:8月更文挑战
SpEL是Spring提供的一种运行时表达式,可以在运行时按照表达式进行计算
入门介绍
基本概述
能在运行时构建复杂表达式、存取对象属性、对象方法调用等等
- 基本表达式
- 类相关表达式
- 集合相关表达式
- 其他表达式
示例分析
ExpressionParser parser = new SpelExpresssionParser();
Expression expressio = parser.parseExpression("('Hello'+'word').concat(#end)");
EvaluationContext context = new StandardEvaluationContext();
context.setVariable("end","!");
System.out.println(expression.getValue(context));
工作原理
概念
- 表达式
- 解析器
- 上下文
- 根对象及活动上下文对象
工作原理
- 定义表达式
- 定义解析器ExpressionParser
- 生成记号流
- 生成抽象语法树
- 生成Expression接口
- 定义上下文对象
- 根据表达式求值
主要接口
- ExpressionParser接口
- EvaluationContext接口
- Expression接口
配置风格
XML风格的配置
定义Bean时注入,默认使用"#{SpEL表达式}"表示,其中"#root"根对象默认可以认为是ApplicationContext,只有ApplicationContext实现默认支持SpEL,获取对象属性其实是获取容器中的Bean。
注解风格
使用@Value注解指定SpEL表达式
操作范围
字面值
最简单的SpEL表达式仅包含一个简单的字面值:
<property name="num" value="#{5}" />
Bean及Bean的属性或方法
- 引用Bean本身
<porperty name="bean2" value="#{bean1}"/>
<porperty name="bean2" ref="bean1"/>
- 引用Bean的属性
<bean id="bean2" class="com.jike.***.Bean2">
<property name="name" value="#{bean1.name}"/>
</bean>
同下:
Bean2 bean2 = new Bean2();
bean2.setName(bean1.getName());
- 引用Bean的方法
<property name="name" value="#{bean2.getName()}"/>a
<property name="name" value="#{bean2.getName.toUpperCase()}"/>
<!-- 返回null时,不执行后面的方法 -->
<property name="name" value="#{bean2.getName?.toUpperCase()}"/>
类的方法和常量
<property name="pi" value="#{T(java.lang.Math).PI}"/>
<property name="randomNumber" value="#{T(java.lang.Math).random()}"/>
运算符
运算符类型
运算符类型 | 运算符示例 |
---|---|
数值运算 | +、-、*、/、%、^ |
比较运算 | <、>、==、>=、<=、lt、gt、eg、le、ge |
逻辑运算 | and、or、not、| |
条件运算 | ?:(ternary)、?:(Elvis) |
正则表达式 | matches |
数值运算
加、减、乘、除、取余、乘方、字符串连接
<property name="" value="#{counter.total+42}"/>
<property name="" value="#{counter.total+42}"/>
<property name="" value="#{2*T(java.lang.Math).PI*counter.total}"/>
<property name="" value="#{counter.total/counter.count}"/>
<property name="" value="#{counter.total%counter.count}"/>
<property name="" value="#{T(java.lang.Math).PI*counter.total^2}"/>
<property name="" value="#{'张'+''+'三'}"/>
比较运算
<property name="equal" value="#{counter.total == 100}"/>
<property name="equal" value="#{counter.total eq 100}"/>
逻辑运算符
<property name="handsome" value="#{counter.total == 100 and counter.count gt 100}"/>
<property name="equal" value="#{counter.total eq 100}"/>
条件运算符
?:
<property name="handsome" value="#{person.height gt 170 ? true :false}"/>
<!-- 默认true时使用条件 -->
<property name="name" value="#{person.name ?: 'Tom'}"/>
正则表达式
matches运算符,匹配成功返回true
<property name="validEmail" value="#{admin.email matches '[a-zA-Z0-9]+@[z-aA-Z0-9.-]+\\.com'}"
集合操作
SpEL可以引用集合中的某个成员,具有基于属性值来过滤集合成员的能力:
- 访问集合成员
- 查询集合成员
- 投影集合
访问集合成员
使用uitl命名空间中的util:list元素定义一个List集合
<util:list id="cities">
<bean class="" p:name="" p:state="IL" p:population="2853114"/>
<bean class="" p:name="" p:state="1L" p:population="2853114"/>
<bean class="" p:name="" p:state="1L" p:population="2853114"/>
<bean class="" p:name="" p:state="1L" p:population="2853114"/>
……
</util:list>
查询集合成员
<!-- 查询人口大于100000的所有城市 -->
<property name="BigCities" value="#{cities.?[population gt 100000]}"/>
<!-- 查询人口大于100000的第一个城市 -->
<property name="BigCity1" value="#{cities.^[population gt 100000]}"/>
<!-- 查询人口大于100000的最后一个城市 -->
<property name="BigCity2" value="#{cities.$[population gt 100000]}"/>
投影集合
<property name="cityName1" value="#{cities.![name]}"/>
<property name="cityName1" value="#{cities.![name+','+state]}"/>
<property name="BigCitiesName" value="#{cities.?[population gt 100000].![name]}"/>