接口或类 | 功能性说明 |
顶层接口(parser{configuration,context}) |
|
ExpressionParser [i] | 建议使用的实现类:SpelExpressionParser [c] 构造时可注册配置选项:SpelParserConfiguration [c] 调用解析方法时(`parse*`)可获取表达式接口:Expression [i] |
SpelParserConfiguration [c] | 可选的配置选项有编译模式的选择,类加载器的指定与否,是否自动初始化等等 其中编译模式,关联了枚举类:SpelCompilerMode [e] |
Expression [i] | 可对 el表达式 进行读写操作的接口,有其setter和getter方法实现. 另重写行为,可配置 el表达式 求值时的上下文:EvaluationContext [i] |
EvaluationContext [i] | 求值上下文的接口,spring 4.x中有两个实现类,即简易的和标准的实现. 可操作el表达式的属性,构造器,类型,rootObject等等. SimpleEvaluationContext [c] StandardEvaluationContext [c] |
建议使用的实现类 |
|
SpelExpressionParser [c] | 表达式解析的实现类 重写的构造器中,可注册解析的配置选项.(configuration) 在解析的方法中(parse*),可获取表达式的接口实例.(expression) |
SpelParserConfiguration [c] | 可组合选择自需的解析模式 1,设置编译模式,有三种候选项. spelCompilerMode 2,设置解析式的类加载器. classLoader 3,设置是否自动初始化空引用. auto-grow 4,设置是否自动初始化集合中的空元素. auto-grow 5,设置自动初始化集合长度的阈值. limits |
SpelCompilerMode [e] | 内置了三种解析模式 off , 关闭,默认的选项 mixed , 混合模式 immediate , 即时模式 |
StandardEvaluationContext [c] | 标准的求值上下文.也可根据不同场景,使用SimpleEvaluationContext [c]. 此类中有大量的setter方法,可设置rootObject; property; constructor; method; var; type; 等等. |
属性占位符的格式是: ` ${ expression } `语法 | 格式 | 使用 |
字面量(literal expression) | 使用单引号,或者通过转义符使用双引号 支持字符串,算术运算,空值处理,进制转换等 |
" \"jack\" " ; " 2E-23-12 " ; " null " |
容器(properties,lists,maps,arrays) | 直接访问,可使用调用符访问其成员 | " list.get(0) " |
索引器(indexers) | 使用符号`[]`,可直接访问其成员 | " list[0] " |
内部初始化(inner lists/maps) | 使用格式:{value}或{key:value},成员以逗号分隔 | " {0,1,2,3,4} "或" {0:name,1:age,3:gender} " |
数组构造器(属于new操作符) | 直接在表达式中,可初始化并分配数组 | " new int[3] ";支持所有的数组初始化语法 |
操作符 1,在xml文档中,因符号解析冲突问题,部分操作符的替代方案,使用英文字符如下: lt (<), gt (>), le (#), ge(>=), eq (==), ne (!=), div (/), mod (%), not (!) 2,可在parse*的重构方法中,使用#{},涉及的操作类是TemplateParserContext. |
||
比较操作符 | 可使用比如>,<,=等等的比较运算符 | \ |
逻辑操作符 | 表达式中的逻辑操作符,使用and,or和not | \ |
算术操作符 | 表达式支持的有+,-,*,/,%,^(平方)等等 | \ |
instanceof操作符 | 可直接在表达式内使用,使用空格区分 | " obj instanceof Type ",返回Boolean类型 |
matches操作符 | 正则匹配,支持大部分的匹配符 | " str matches 'regex expression' " |
类型引用操作符---T() | 使用符号: T(),可查看TypeLocator接口, java.lang包中的引用不需全类名,反之使用. |
" T(Math).random() " |
new操作符 | 使用new操作符可实例化对象,但应使用全类名 | " new java.util.ArrayLis>() " |
变量引用操作符---# | 与求值上下文有关,内置的有#this和#root, 也可设置方法引用,设置求值上下文实例 |
" #var " |
bean引用操作符---@ | 可引用容器中注册的bean,依据beanName | " @beanName " |
三元操作符---` ? : ` | 表达式支持三元操作符 | \ |
Elvis操作符 | Groovy语言中替代三元操作符的方案. ?: |
" attr?:\"unknown\" " |
安全导航操作符---? | 来自Groovy语言 考虑空值异常的情况,若使用?操作符, 遇到此异常时,不抛出,而是返回null. |
" list?.get(12) " |
集合选择操作符---.? | 集合中选择满足条件的元素,可结合变量引用 操作符使用 |
" list.?[#this>0] " |
集合转换操作符---.! | 将集合中的取出的元素,转换则条件返回的结果 | " list.![#this<0] " |
使用的jar包依赖
org.springframework
spring-context
4.3.20.RELEASE
org.springframework
spring-test
4.3.20.RELEASE
junit
junit
4.12
xml配置文件,注册解析器,解析配置,求值上下文,以及测试所使用的bean
jack
43
0
43
54
98
3
2
1
基于java的配置类
package siye.el;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
@Configuration
@ComponentScan("siye.el")
@ImportResource(locations = "classpath:/config.xml")
public class ConfigClass
{
}
辅助测试el表达式的注册bean类
package siye.el;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component("userInner")
@Scope("prototype")
public class User
{
public Properties props;
public int[] intarr;
public List list;
public Map map;
public String name;
public User getInstance()
{
return new User();
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public Properties getProps()
{
return props;
}
public void setProps(Properties props)
{
this.props = props;
}
public int[] getIntarr()
{
return intarr;
}
public void setIntarr(int[] intarr)
{
this.intarr = intarr;
}
public List getList()
{
return list;
}
public void setList(List list)
{
this.list = list;
}
public Map getMap()
{
return map;
}
public void setMap(Map map)
{
this.map = map;
}
}
测试类;basic,测试字面量解析;collections,测试集合容器的操作;operator,测试el表达式的操作符等
package siye.el;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = ConfigClass.class)
public class UnitTestBasic
{
@Autowired
private SpelExpressionParser parser;
@Test
public void test()
{
// 解析字符串
String stringValue =
parser.parseExpression("\"jack\"").getValue(String.class);
System.out.println(stringValue);
// 解析浮点数
// 支持指数表示法,符号和小数点.
Double doubleValue =
parser.parseExpression("3.4232365E+23").getValue(Double.class);
System.out.println(doubleValue.toString());
// 解析整数
// 支持进制的表达方式.
Integer intValue =
parser.parseExpression("0xfffff").getValue(Integer.class);
System.out.println(intValue);
// 解析布尔值
Boolean booleanValue =
parser.parseExpression("false").getValue(Boolean.class);
System.out.println(booleanValue);
// 解析空值.
// 注意null没有类类型.
Object nullValue =
parser.parseExpression("null").getValue(Object.class);
System.out.println(nullValue);
}
}
package siye.el;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
/*
* 1,spel的语法,properties,lists,arrays,maps,indexers(索引器)
* 其中索引器的格式是使用符号`[]`直接访问其元素.
* 2,spel中的inner lists 和 inner maps.
* 使用符号{value}和{key:value},多元素以符号`,`间隔.
* 3,spel中,可直接使用数组的构造器创建数组.
*/
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = ConfigClass.class)
public class UnitTestCollections
{
@Autowired
private ApplicationContext context;
@Autowired
@Qualifier("user")
private User user;
@Autowired
SpelExpressionParser parser;
@Autowired
StandardEvaluationContext evaluationContext;
@Test
public void test()
{
System.out.println(context);
System.out.println(user);
System.out.println(parser);
System.out.println(evaluationContext);
}
// 解析properties
@Test
public void test1()
{
Expression expression =
// parser.parseExpression("props.getProperty(\"name\")");
parser.parseExpression("props[name]");
String value = expression.getValue(user, String.class);
System.out.println(value);
}
// 解析arrays
@Test
public void test2()
{
Expression expression = parser.parseExpression("intarr[1]");
Integer intvalue = expression.getValue(user, int.class);
System.out.println(intvalue);
}
// 解析lists和indexers(索引器)
@Test
public void test3()
{
// 测试lists
Expression expression = parser.parseExpression("list.get(0)");
Integer intvalue = expression.getValue(user, Integer.class);
System.out.println(intvalue);
// 测试indexers(索引器)
Expression expression2 = parser.parseExpression("list[2]");
expression2.setValue(evaluationContext, user, 23);
System.out.println(user.list);
}
// 测试maps
@Test
public void test4()
{
// 采用indexers(索引器)的方式访问.
Expression expression = parser.parseExpression("map[0]");
String value = expression.getValue(user, String.class);
System.out.println(value);
}
// spel的内部初始化,inner lists和inner maps
// 使用符号{value}和{key:value},多元素以符号`,`间隔.
@Test
public void test5()
{
// inner lists
Expression expression =
parser.parseExpression("{'jack','rose','lili'}");
List> list = expression.getValue(evaluationContext, List.class);
System.out.println(list);
// inner maps
Expression expression2 =
parser.parseExpression("{0:'jack',1:'rose',2:'lili'}");
Map, ?> map = expression2.getValue(evaluationContext, Map.class);
System.out.println(map);
}
// 使用数组的构造器
@Test
public void test6()
{
// 还可以使用其他创建形式
// new int[num]
// new int[num0][num1]
Expression expression = parser.parseExpression("new int[]{1,2,3,4,5}");
int[] intarr = expression.getValue(evaluationContext, int[].class);
System.out.println(Arrays.toString(intarr));
}
}
package siye.el;
import java.util.ArrayList;
import java.util.Arrays;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.expression.Expression;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = ConfigClass.class)
public class UnitTestOperator
{
@Autowired
ApplicationContext context;
@Autowired
SpelExpressionParser parser;
@Autowired
StandardEvaluationContext evaluationContext;
@Autowired
@Qualifier("userInner")
private User user;
@Autowired
@Qualifier("user")
private User userxml;
@Test
public void test()
{
System.out.println(user);
System.out.println(parser);
System.out.println(evaluationContext);
}
/*
* spel中常使用的操作符有,
* 比较操作符,比如>,<,=,e.g.
* 逻辑操作符,and,or,not,
* 算术操作符,+,-,%,^,e.g.
* instanceof操作符,
* matches操作符,
* T()类型引用操作符,
* new操作符,可以使用new操作符实例化对象,但必须是全类名!
* `#`,变量操作符,是用来操作变量的,内置的变量有#this和#root
* `.`,属性操作符
* `?`,搜寻操作符
* `@\&`,操作bean
*
* 补充说明:
* xml文档中的literal-operator替代形式
* lt (<), gt (>), le (#), ge(>=), eq (==),
* ne (!=), div (/), mod (%), not (!)
*/
// 使用比较操作符.
@Test
public void test1()
{
Expression expression = parser.parseExpression("2>3");
Boolean value = expression.getValue(boolean.class);
System.out.println(value);
}
// 使用逻辑操作符.
@Test
public void test2()
{
Expression expression = parser.parseExpression("true and false");
Boolean value = expression.getValue(boolean.class);
System.out.println(value);
}
// 使用算术操作符.
@Test
public void test3()
{
Expression expression = parser.parseExpression("1.22 + 3.44");
Double value = expression.getValue(double.class);
System.out.println(value);
}
// 使用instanceof操作符
@Test
public void test4()
{
Expression expression =
parser.parseExpression("'jack' instanceof T(java.lang.String)");
Boolean value = expression.getValue(boolean.class);
System.out.println(value);
}
// 使用matches操作符
@Test
public void test5()
{
Expression expression =
parser.parseExpression("'5.001' matches '^\\d+(\\.\\d{2})$'");
Boolean value = expression.getValue(boolean.class);
System.out.println(value);
}
// 使用T()操作符
// 说明,
// 标准的求值上下文,StandardEvaluationContext.
// 其借用的是typeLocator属性来查询类型的,而TypeLocator接口有默认的实现
// StandardTypeLocator类.可查看其构造器,默认把`java.lang`包注册进去了.
// 故,
// 使用T()操作符的时候,若引用的是java.lang包的类,就不需要前缀类,
// 但若是其他类型,必须使用全类名.
@Test
public void test6()
{
Expression expression =
parser.parseExpression("T(java.lang.Math).random()");
Double value = expression.getValue(double.class);
System.out.println(value);
}
// 使用new操作符,必须使全类名.
@Test
public void test7()
{
Expression expression = parser.parseExpression("new siye.el.User()");
User value = expression.getValue(User.class);
System.out.println(value);
}
// spel内部使用变量.借用符号`#`
@Test
public void test8()
{
// 在环境中新建一个变量.
evaluationContext.setVariable("newname", "jack");
// 使用该变量,#newname
Expression expression = parser.parseExpression("name = #newname");
expression.getValue(evaluationContext, user);
System.out.println(user.name);
}
// function language
// 变量引用,也可以引用操作方法.
// 使用操作麻烦,不推荐使用,有符号`.`的替代方案.
@Test
public void test9()
{
try
{
evaluationContext.setVariable("test",
Arrays.class.getMethod("toString", int[].class));
Object value =
parser.parseExpression("#test(intarr)").getValue(
evaluationContext, userxml);
System.out.println(value);
} catch (Exception e)
{
}
}
// 测试#this和#root
// this,表示当前求值环境中处理的对象.
// root,表示求值环境中设置的rootObject.
@SuppressWarnings("serial")
@Test
public void test10()
{
// 测试#this
evaluationContext.setVariable("list", new ArrayList()
{
{
add(0);
add(1);
add(2);
add(3);
add(4);
}
});
Object thisvalue =
parser.parseExpression("#list.?[#this>3]").getValue(
evaluationContext);
System.out.println(thisvalue);
// 测试#root
evaluationContext.setRootObject(userxml);
Object rootvalue =
parser.parseExpression("#root").getValue(evaluationContext);
System.out.println(rootvalue);
}
// bean reference
// @操作符,用来引用容器中配置的bean
@Test
public void test11()
{
// 获取bean工厂的解析对象.
BeanFactoryResolver factoryResolver = new BeanFactoryResolver(context);
// 设置bean的解析对象.
evaluationContext.setBeanResolver(factoryResolver);
Expression expression = parser.parseExpression("@user");
Object value = expression.getValue(evaluationContext);
System.out.println(value);
}
// 三元操作符
// `?:`
@Test
public void test12()
{
Expression expression = parser.parseExpression("2<5?0:1");
Integer value = expression.getValue(evaluationContext, int.class);
System.out.println(value);
}
// Elvis操作符
// ?:,表示如果var取值为null,则取value值.
// Elvis操作符实际上是三元操作符的简写形式.
//
// 常识补充,其是Groovy语言中的三元操作符.
@Test
public void test13()
{
user.list = null;
Expression expression = parser.parseExpression("list?:'Unknown'");
Object value = expression.getValue(evaluationContext, user);
System.out.println(value);
}
// 安全导航操作符
// 使用符号?
// 来自Groovy的语法.
// 主要是用来防止抛出空指针异常的,若是无法求值,就返回null.
@Test
public void test14()
{
Expression expression = parser.parseExpression("list?.get(10)");
Object value = expression.getValue(evaluationContext, user);
System.out.println(value);
}
// 集合选择器
// .?[ selection expression ]
//
@Test
public void test15()
{
Expression expression = parser.parseExpression("list.?[#this>1]");
Object value = expression.getValue(evaluationContext, userxml);
System.out.println(value);
}
// 集合转换器
// .![ projection expression ]
//
@Test
public void test16()
{
Expression expression = parser.parseExpression("list.![#this>2]");
Object value = expression.getValue(evaluationContext, userxml);
System.out.println(value);
}
// 使用spel的模板环境.
// #{ spel expression }
// 可查看接口ParserContext,及其实现类TemplateParserContext.
@Test
public void test17()
{
Expression expression =
parser.parseExpression("随机求取的值是:#{T(Math).random()}",
new TemplateParserContext());
Object value = expression.getValue();
System.out.println(value);
}
}