SpEL表达式总结张的反义词
前⾔
SpEL(Spring Expression Language),即Spring表达式语⾔,是⽐JSP的EL更强⼤的⼀种表达式语⾔。为什么要总结SpEL,因为它可以在运⾏时查询和操作数据,尤其是数组列表型数据,因此可以缩减代码量,优化代码结构。个⼈认为很有⽤。
⽬录
前⾔
⼀. ⽤法
1. @Value
2. 配置
3. Expression
⼆. 表达式语法
关于桥的民间故事
1. 直接量表达式
2. 直接使⽤java代码new/instance of
3. 使⽤T(Type)
4. 变量
5. ⽅法调⽤
放飞梦想
6. 运算符表达式
⼀. ⽤法
SpEL有三种⽤法,⼀种是在注解@Value中;⼀种是XML配置;最后⼀种是在代码块中使⽤Expression。
1. @Value
//@Value能修饰成员变量和⽅法形参
//#{}内就是表达式的内容
@Value("#{表达式}")
public String arg;
如果修饰成员变量,是从Spring容器中按照SpEL表达式筛选修改数据后,赋值给所修饰的变量;如果修饰⽅法形参,则是过滤传进来的参数值。
2. <bean>配置
<bean id="xxx" class="com.">
<!-- 同@Value,#{}内是表达式的值,可放在property或constructor-arg内 -->
<property name="arg" value="#{表达式}">
</bean>
⽤法跟注解@ Value修饰形参类似
3. Expression
import pression.Expression;
import pression.ExpressionParr;
import pression.spel.standard.SpelExpressionParr;
import pression.spel.support.StandardEvaluationContext;
唐临public class SpELTest {
public static void main(String[] args) {
//创建ExpressionParr解析表达式
ExpressionParr parr = new SpelExpressionParr();
//表达式放置
Expression exp = parr.parExpression("表达式");
//执⾏表达式,默认容器是spring本⾝的容器:ApplicationContext
Object value = Value();
/
**如果使⽤其他的容器,则⽤下⾯的⽅法*/
//创建⼀个虚拟的容器EvaluationContext
StandardEvaluationContext ctx = new StandardEvaluationContext();
//向容器内添加bean
BeanA beanA = new BeanA();
ctx.tVariable("bean_id", beanA);
//tRootObject并⾮必须;⼀个EvaluationContext只能有⼀个RootObject,引⽤它的属性时,可以不加前缀
ctx.tRootObject(XXX);
//getValue有参数ctx,从新的容器中根据SpEL表达式获取所需的值我懂了她
Object value = Value(ctx);
}
}
⽤法⽐较灵活,可以在代码中使⽤SpEL进⾏数据的过滤和修改
以上概念还可以参考:
⼆. 表达式语法
表达式语法可以参考:
1. 直接量表达式
"#{'Hello World'}"
2. 直接使⽤java代码new/instance of
此⽅法只能是java.lang 下的类才可以省略包名
Expression exp = parr.parExpression("new Spring('Hello World')");
3. 使⽤T(Type)
使⽤“T(Type)”来表⽰java.lang.Class实例,同样,只有java.lang 下的类才可以省略包名。此⽅法⼀般⽤来引⽤常量或静态⽅法
parr.parExpression("T(Integer).MAX_VALUE");
4. 变量
获取容器内的变量,可以使⽤“#bean_id”来获取。有两个特殊的变量,可以直接使⽤。
#this 使⽤当前正在计算的上下⽂
#root 引⽤容器的root对象
String result2 = parr.parExpression("#root").getValue(ctx, String.class);
String s = new String("abcdef");
ctx.tVariable("abc",s);
//取id为abc的bean,然后调⽤其中的substring⽅法
parr.parExpression("#abc.substring(0,1)").getValue(ctx, String.class);
5. ⽅法调⽤
与Java代码没有什么区别,可见上⾯的例⼦
可以⾃定义⽅法,如下:
Method parInt = DeclaredMethod("parInt", String.class);
ctx.tVariable("parInt2", parInt);
String expression1 = "#parInt('3') == #parInt2('3')";
“registerFunction”和“tVariable”都可以注册⾃定义函数,但是两个⽅法的含义不⼀样,推荐使⽤“registerFunction”⽅法注册⾃定义函数。
6. 运算符表达式
算数表达式(“1+2-3*4/2″)
⽐较表达式(“1>2”)
逻辑表达式(“2>1 and (!true or !fal)”)
赋值表达式(“#variableName=value”)
三⽬表达式(“表达式1?表达式2:表达式3”)
正则表达式(“123′ matches ‘\\d{3}”)
等运算符,都可以直接放在SpEL中
7. Elvis运算符
是三⽬运算符的特殊写法,可以避免null报错的情况
公司团队
name != null? name : "other"新生儿鼻塞怎么办
//简写为:
name?:"other"
8. 安全保证
为了避免操作对象本⾝可能为null,取属性时报错,定义语法
语法: “对象?.变量|⽅法”
list?.length
当对象为null时,直接返回“null”,不会抛出NullPointerException
9. 集合定义
使⽤“{表达式,……}”定义List,如“{1,2,3}”
对于字⾯量表达式列表,SpEL会使⽤java.util.Collections.unmodifiableList ⽅法将列表设置为不可修改。
List<Integer> result1 = parr.parExpression("{1,2,3}").getValue(List.class);
10. 集合访问
SpEL⽬前⽀持所有集合类型和字典类型的元素访问
语法:“集合[索引]”、“map[key]”
EvaluationContext context = new StandardEvaluationContext();
//即(0)
int result1 = parr.parExpression("{1,2,3}[0]").getValue(int.class);
//list获取某⼀项
Collection<Integer> collection = new HashSet<Integer>();
collection.add(1);
collection.add(2);
context.tVariable("collection", collection);
int result2 = parr.parExpression("#collection[1]").getValue(context, int.class);
//map获取
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("a", 1);
context.tVariable("map", map);
int result3 = parr.parExpression("#map['a']").getValue(context, int.class);
11. 集合修改
可以使⽤赋值表达式或Expression接⼝的tValue⽅法修改;
//赋值语句
int result = parr.parExpression("#array[1] = 3").getValue(context, int.class);
//rValue⽅法
parr.parExpression("#array[2]").tValue(context, 4);
12. 集合选择
通过⼀定的规则对及格进⾏筛选,构造出另⼀个集合
顽石互动语法:“(list|map).?[选择表达式]”
选择表达式结果必须是boolean类型,如果true则选择的元素将添加到新集合中,fal将不添加到新集合中。parr.parExpression("#collection.?[#this>2]").getValue(context, Collection.class);
上⾯的例⼦从数字的collection集合中选出数字⼤于2的值,重新组装成了⼀个新的集合
13. 集合投影
根据集合中的元素中通过选择来构造另⼀个集合,该集合和原集合具有相同数量的元素语法:“SpEL使⽤“(list|map).![投影表达式]”
public class Book {
public String name; //书名
public String author; //作者
public String publisher; //出版社
public double price; //售价
public boolean favorite; //是否喜欢
}
public class BookList {
@Autowired
protected ArrayList<Book> list = new ArrayList<Book>() ;
protected int num = 0;
}
将BookList的实例映射为bean:readList,在另⼀个bean中注⼊时,进⾏投影
//从readList的list下筛选出favorite为true的⼦集合,再将他们的name字段投为新的list
@Value("#{list.?[favorite eq true].![name]}")
private ArrayList<String> favoriteBookName;