基本表达式
字面量表达式
字符串、数字类型(int、long、float、double)、boolean、null类型
类型 | 示例 |
---|---|
字符串 | String str=parser.parseExpression(“‘Hello’”).getValue(String.class); |
数字类型 | int i=parser.parseExpression(“1”).getValue(Integer.class); |
int i=parser.parseExpression(“0xf”).getValue(Integer.class);//十六进制 | |
布尔类型 | boolean b1=parser.parseExpression(“false”).getValue(boolean.class); |
boolean b1=parser.parseExpression(“true”).getValue(boolean.class); | |
null类型 | Object object=parser.parseExpression(“null”).getValue(Object.class); |
2. 算术运算表达式
类型 | 示例 |
---|---|
加减乘除 | int i=parser.parseExpression(“4+2*3/2”).getValue(Integer.class); |
求余 | int i=parser.parseExpression(“4%3”).getValue(Integer.class); |
幂运算 | int i=parser.parseExpression(“2^4”).getValue(Integer.class); |
3. 关系表达式
等于(==)、不等于(!=)、大于(>)、小于(<)、区间(between)
between运算符右边操作数必须是列表类型,且只能有2个元素,区间包含边界值,如 boolean b1=parser.parseExpression(“1 between {1,2}”).getValue(boolean.class);
4. 逻辑表达式
与(and)或(or)非(!或者NOT),不支持java的&& 和 ||
5. 字符串连接及截取表达式
使用”+”连接,如“‘hello’+’world’”
使用“‘String’[Index]”截取,但只支持截取一个字符,如“‘hello’[0]”
6. 三目运算及Elivis运算表达式
三目运算:表达式1?表达式2:表达式3
Elivis运算:表达式1?表达式2(表达式1不为null则返回表达式1,否则返回表达式2)
7. 正则表达式
8. 括号优先级表达式
类相关表达式
1)类类型表达式
使用“T(type)”来表示java.lang.Class实例,“Type”必须是类全限定名,java.lang包除外,即除了该包,其他类都需要指定包名;还可以访问静态方法以及静态字段
ClassTypeTest .java
package com.test;
import org.junit.Test;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
public class ClassTypeTest {
@Test
public void test(){
ExpressionParser parser=new SpelExpressionParser();
//java.lang包访问
Class<String> result=parser.parseExpression("T(String)").getValue(Class.class);
//静态变量
int result2=parser.parseExpression("T(Integer).MIN_VALUE").getValue(int.class);
//静态方法
int result3=parser.parseExpression("T(Integer).parseInt('1')").getValue(int.class);
System.out.println(result.equals(String.class));
System.out.println(result2);
System.out.println(result3);
}
}
2)类实例化
使用java关键字“new”,类名必须是全限定名
String result4 =parser.parseExpression("new String('hello')").getValue(String.class);
3)instanceof
4)变量定义以及引用
通过EvaluationContext接口的setVariable(Stirng name,String value)方法定义;在表达式中使用“#name”引用;“#root”使用根对象;“#this”使用上下文对象
ClassTypeTest .java
package com.test;
import org.junit.Test;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
public class ClassTypeTest {
@Test
public void test(){
ExpressionParser parser=new SpelExpressionParser();
EvaluationContext context=new StandardEvaluationContext();
context.setVariable("variable", "hello");
String result =parser.parseExpression("#variable").getValue(context,String.class);
context=new StandardEvaluationContext("hello");
String result2 =parser.parseExpression("#root").getValue(context,String.class);
String result3 =parser.parseExpression("#root").getValue(context,String.class);
System.out.println(result);
System.out.println(result2);
System.out.println(result3);
}
}
5) 自定义函数
只支持静态方法注册为自定义函数;使用StandardEvaluationContext的setVariable方法进行注册自定义函数;
ClassTypeTest .java
package com.test;
import java.lang.reflect.Method;
import org.junit.Test;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
public class ClassTypeTest {
@Test
public void test()throws Exception{
ExpressionParser parser=new SpelExpressionParser();
EvaluationContext context=new StandardEvaluationContext();
Method parseInt=Integer.class.getDeclaredMethod("parseInt", String.class);
context.setVariable("parseInt1", parseInt);
String result =parser.parseExpression("#parseInt1('1')").getValue(context,String.class);
System.out.println(result);
}
}
6)赋值表达式
SpEL允许给自定义变量赋值也允许给对象赋值,使用“#name=value”可以赋值
package com.test;
import java.lang.reflect.Method;
import org.junit.Test;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
public class ClassTypeTest {
@Test
public void test()throws Exception{
ExpressionParser parser=new SpelExpressionParser();
EvaluationContext context=new StandardEvaluationContext("root or this(context)");
context.setVariable("variable", "variable");
String result=parser.parseExpression("#variable='value'").getValue(context,String.class);
String result2=parser.parseExpression("#variable=#root").getValue(context,String.class);
String result3=parser.parseExpression("#variable=#this").getValue(context,String.class);
System.out.println(result);
System.out.println(result2);
System.out.println(result3);
}
}
7)对象属性存取以及安全导航表达式
- 取值方式:”对象.属性.属性“
- SpEL属性首字母不区分大小写
- SpEL引入了Grooby语言中的安全导航运算符“(对象|属性)?.属性”,“?”前的表达式若为NULL则抛出异常并且返回null
- 修改属性值可以通过赋值表达式或者Expression的SetValue方法
package com.test;
import java.lang.reflect.Method;
import java.util.Date;
import org.junit.Test;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
public class ClassTypeTest {
@Test
public void test()throws Exception{
Date date =new Date();
ExpressionParser parser=new SpelExpressionParser();
EvaluationContext context=new StandardEvaluationContext(date);
//1访问上下文对象的属性或者方法可以直接使用属性名或者方法名
int result=parser.parseExpression("year").getValue(context,int.class);
//2给属性赋值
parser.parseExpression("year").setValue(context, 123);
int result2=parser.parseExpression("year").getValue(context,int.class);
//3安全访问
context=new StandardEvaluationContext();
Object result3=parser.parseExpression("#root?.year").getValue(context,Object.class);
System.out.println(date.getYear());
System.out.println(result);
System.out.println(result2);
System.out.println(result3);
}
}
打印结果
123
115
123
null
8)对象方法调用
和java语法一样
package com.test;
import java.lang.reflect.Method;
import java.util.Date;
import org.junit.Test;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
public class ClassTypeTest {
@Test
public void test()throws Exception{
Date date =new Date();
ExpressionParser parser=new SpelExpressionParser();
EvaluationContext context=new StandardEvaluationContext(date);
String result=parser.parseExpression("'hello'.indexOf('l')").getValue(context,String.class);
//根对象可直接调用方法
int result2=parser.parseExpression("getYear()").getValue(context,int.class);
System.out.println(date.getYear());
System.out.println(result);
System.out.println(result2);
}
}
9)bean引用
用“@beanName”来引用bean,引用时需要使用BeanResolver接口来查找bean,Spring提供BeanFactoryResolver来实现
ResourceUtil .java
package com.resource;
import java.io.IOException;
import java.io.InputStream;
import org.springframework.core.io.Resource;
public class ResourceUtil {
private static InputStream is=null;
public static void stream(Resource resource ){
try {
//获取文件资源输入流
is=resource.getInputStream();
//读取资源
byte[] byteArray=new byte[is.available()];
is.read(byteArray);
System.out.println(new String(byteArray));
} catch (IOException e) {
e.printStackTrace();
}
finally{
try {
//关闭流
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
ResourceBean .java
package com.resource;
import org.springframework.core.io.Resource;
public class ResourceBean {
private Resource resource;
public Resource getResource() {
return resource;
}
public void setResource(Resource resource) {
this.resource = resource;
}
}
applicationContextResource.xml
<bean id="resourceBean2" class="com.resource.ResourceBean">
<property name="resource" value="classpath:applicationContextResource.xml"/>
</bean>
测试类
package com.test;
import org.junit.Test;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import com.resource.ResourceBean;
import com.resource.ResourceUtil;
public class ClassTypeTest {
@Test
public void test()throws Exception{
ExpressionParser parser=new SpelExpressionParser();
StandardEvaluationContext context=new StandardEvaluationContext();
ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContextResource.xml");
ctx.refresh();
context.setBeanResolver(new BeanFactoryResolver(ctx));
ResourceBean result=parser.parseExpression("@resourceBean2").getValue(context,ResourceBean.class);
ResourceUtil.stream(result.getResource());
}
}
集合相关表达式
1)内联List
“{1,2,3}”将返回一个整形的ArrayList,而“{}”将返回一个空的List,对于字面量表达式列表,SpEL会使用java.util.Collections.unmodifiableList方法将列表设置为不可以修改
public class ClassTypeTest {
@Test
public void test()throws Exception{
ExpressionParser parser=new SpelExpressionParser();
List<Integer> list1=parser.parseExpression("{1,2,3}").getValue(List.class);
List<Integer> list2=parser.parseExpression("{}").getValue(List.class);
for(Integer i:list1){
System.out.println(i);
}
System.out.println(list2.size());
try {
//不可修改
list2.set(0, 4);
} catch (Exception e) {
e.printStackTrace();
}
}
}
只要列表中有一个不是字面量表达式,将返回原始List,并不会作不可修改处理
package com.test;
import java.util.List;
import org.junit.Test;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
public class ClassTypeTest {
@Test
public void test()throws Exception{
ExpressionParser parser=new SpelExpressionParser();
List<Integer> list1=parser.parseExpression("{1,2+1,3}").getValue(List.class);
try {
//可修改
list1.set(0, 4);
for(Integer i:list1){
System.out.println(i);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
2)内联数组
只在定义时进行多维数组初始化
int[][][] arr=parser.parseExpression("new int[1][2][3]").getValue(int[][][].class);
3)集合和map的访问
使用“集合[索引]”访问集合元素,使用“map[key]”访问字典元素
public class ClassTypeTest {
@Test
public void test()throws Exception{
ExpressionParser parser=new SpelExpressionParser();
EvaluationContext context =new StandardEvaluationContext();
List<Integer> list=new ArrayList<Integer>();
Map<String, String> map=new HashMap<String, String>();
list.add(0, 1);
map.put("hello", "girl");
context.setVariable("list", list);
context.setVariable("map", map);
int i=parser.parseExpression("#list[0]").getValue(context,int.class);
String str=parser.parseExpression("#map['hello']").getValue(context,String.class);
System.out.println(i);
System.out.println(str);
}
4)列表、map、数组元素修改
可以使用赋值表达式或者Expression接口的setValue方法修改
public class ClassTypeTest {
@Test
public void test()throws Exception{
ExpressionParser parser=new SpelExpressionParser();
EvaluationContext context =new StandardEvaluationContext();
List<Integer> list=new ArrayList<Integer>();
Map<String, String> map=new HashMap<String, String>();
list.add(0, 1);
map.put("hello", "girl");
context.setVariable("list", list);
context.setVariable("map", map);
int i=parser.parseExpression("#list[0]=2").getValue(context,int.class);
String str=parser.parseExpression("#map['hello']='boy'").getValue(context,String.class);
System.out.println(i);
System.out.println(str);
parser.parseExpression("#list[0]").setValue(context,3);
parser.parseExpression("#map['hello']").setValue(context,"boys and girls");
i=parser.parseExpression("#list[0]").getValue(context,int.class);
str=parser.parseExpression("#map['hello']").getValue(context,String.class);
System.out.println(i);
System.out.println(str);
}
5)集合投影
SpEL的集合投影指的是根据集合中的元素通过选择来构造另外一个集合,该集合和原集合具有相同数量的元素;SpEL使用”(List|Map).![投影表达式]”来进行投影
public class ClassTypeTest {
@Test
public void test()throws Exception{
ExpressionParser parser=new SpelExpressionParser();
EvaluationContext context =new StandardEvaluationContext();
List<Integer> list=new ArrayList<Integer>();
list.add(0,1);
list.add(1,2);
context.setVariable("list", list);
List<Integer> list2=parser.parseExpression("#list.![#this+1]").getValue(context,List.class);
for(Integer i:list2){
System.out.println(i);
}
}
}
在投影表达式中”#this”表示每个集合或者数组的元素
public class ClassTypeTest {
@Test
public void test() throws Exception {
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = new StandardEvaluationContext();
Map<String, String> map = new HashMap<String, String>();
map.put("k1", "v1");
map.put("k2", "v2");
context.setVariable("map", map);
List<String> list2 = parser.parseExpression("#map.![key+'k']").getValue(context, List.class);
for (String str : list2) {
System.out.println(str);
}
List<String> list3 = parser.parseExpression("#map.![value+'v']").getValue(context, List.class);
for (String str : list3) {
System.out.println(str);
}
}
}
map的投影是List集合,”#this”是map.Entry,所以可以用“value”来获取值,“key”来获取键
6)集合选择
SpEL根据原集合通过条件表达式选择出满足条件的元素并构造为新的集合;使用“(List|Map).?[选择表达式]”,表达式的结果必须是boolean类型,true则添加进新的集合中
public class ClassTypeTest {
@Test
public void test() throws Exception {
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = new StandardEvaluationContext();
Map<String, String> map = new HashMap<String, String>();
map.put("k1", "v1");
map.put("k2", "v2");
context.setVariable("map", map);
Map<String, String> map2 = parser.parseExpression("#map.?[key.contains('1')]").getValue(context, Map.class);
System.out.println(map2.size());
System.out.println(map2.get("k1"));
Map<String, String> map3 = parser.parseExpression("#map.?[!value.contains('2')]").getValue(context, Map.class);
System.out.println(map3.size());
System.out.println(map3.get("k1"));
}
}
注意和集合投影不一样,集合选择map返回的map
表达式模板
SpEL(1)中的ParserContext接口实现来定义表达式是否为模板以及前缀后缀的定义