SpEL全称:Spring Expression Language
所在包:org.springframework.expression
Evaluation
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("'Hello World'");
String message = (String) exp.getValue();
值为’Hello World’。
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("'Hello World'.concat('!')");
String message = (String) exp.getValue();
值为’Hello World!’。
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("'Hello World'.bytes");
byte[] bytes = (byte[]) exp.getValue();
获取字符串的字节数组。
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parserExpression("'Hello World'.bytes.length");
int length = (Integer) exp.getValue();
获取字符串的字节数组的长度
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("new String('hello world').toUpperCase()");
String message = exp.getValue(String.class);
构造一个String然后调用它的toUpperCase()方法。
// Create and set a calendar
GregorianCalendar c = new GregorianCalendar();
c.set(1856, 7, 9);
// The constructor arguments are name, birthday, and nationality.
Inventor tesla = new Inventor("Nikola Tesla", c.getTime(), "Serbian");
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("name"); // Parse name as an expression
String name = (String) exp.getValue(tesla);
// name == "Nikola Tesla"
exp = parser.parseExpression("name == 'Nikola Tesla'");
boolean result = exp.getValue(tesla, Boolean.class);
// result == true
理解EvaluationContext
EvaluationContext 接口被用于解析属性、方法或字段,并帮助执行类型转换。Spring提供两种实现:
SimpleEvaluationContext:基本功能。
StandardEvaluationContext:全部功能。
默认情况下,SpEL使用 org.springframework.core.convert.ConversionService 进行转换服务。
class Simple {
public List<Boolean> booleanList = new ArrayList<Boolean>();
}
Simple simple = new Simple();
simple.booleanList.add(true);
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
// "false" is passed in here as a String. SpEL and the conversion service
// will recognize that it needs to be a Boolean and convert it accordingly.
parser.parseExpression("booleanList[0]").setValue(context, simple, "false");
// b is false
Boolean b = simple.booleanList.get(0);
配置Parser
使用 org.springframework.expression.spel.SpelParserConfiguration。
class Demo {
public List<String> list;
}
// Turn on:
// - auto null reference initialization
// - auto collection growing
SpelParserConfiguration config = new SpelParserConfiguration(true,true);
ExpressionParser parser = new SpelExpressionParser(config);
Expression expression = parser.parseExpression("list[3]");
Demo demo = new Demo();
Object o = expression.getValue(demo);
// demo.list will now be a real collection of 4 entries
// Each entry is a new empty String
SpEL编译
SpEL表达式只有在求值时才会进行表达式计算,如果一个表达式被重复调用的次数很多,性能会下降,SpEL编译就是为了解决这种情况。
编译器可以操作在 org.springframework.expression.spel.SpelCompilerMode 枚举中的三个模式之一:
OFF(默认):关闭。
IMMEDIATE:内部调用第一次后,才会真正使用编译模式。
MIXED:到达一个阈值后,启用编译模式。
使用 SpelParesrConfiguration 配置parser。
SpelParserConfiguration config = new SpelParserConfiguration(SpelCompilerMode.IMMEDIATE,
this.getClass().getClassLoader());
SpelExpressionParser parser = new SpelExpressionParser(config);
Expression expr = parser.parseExpression("payload");
MyMessage message = new MyMessage();
Object payload = expr.getValue(message);
Bean定义中使用Expressions
使用 #{}。
T()表示创建一个实例。
<bean id="numberGuess" class="org.spring.samples.NumberGuess">
<property name="randomNumber" value="#{ T(java.lang.Math).random() * 100.0 }"/>
<!-- other properties -->
</bean>
public class FieldValueTestBean {
@Value("#{ systemProperties['user.region'] }")
private String defaultLocale;
public void setDefaultLocale(String defaultLocale) {
this.defaultLocale = defaultLocale;
}
public String getDefaultLocale() {
return this.defaultLocale;
}
}
语言涉及
Variables
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
context.setVariable("newName", "Mike Tesla");
parser.parseExpression("Name = #newName").getValue(context, tesla);
System.out.println(tesla.getName()) // "Mike Tesla"
#this被定义为目前对象,#root被定义为根上下文对象。
// create an array of integers
List<Integer> primes = new ArrayList<Integer>();
primes.addAll(Arrays.asList(2,3,5,7,11,13,17));
// create parser and set variable 'primes' as the array of integers
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataAccess();
context.setVariable("primes", primes);
// all prime numbers > 10 from the list (using selection ?{...})
// evaluates to [11, 13, 17]
List<Integer> primesGreaterThanTen = (List<Integer>) parser.parseExpression(
"#primes.?[#this>10]").getValue(context);
bean
使用Bean时用 @,使用工厂时用 &。
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
context.setBeanResolver(new MyBeanResolver());
// This will end up calling resolve(context,"something") on MyBeanResolver during evaluation
Object bean = parser.parseExpression("@something").getValue(context);
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
context.setBeanResolver(new MyBeanResolver());
// This will end up calling resolve(context,"&foo") on MyBeanResolver during evaluation
Object bean = parser.parseExpression("&foo").getValue(context);
Elvis Operator
String name = "Elvis Presley";
String displayName = (name != null ? name : "Unknown");
ExpressionParser parser = new SpelExpressionParser();
String name = parser.parseExpression("name?:'Unknown'").getValue(String.class);
System.out.println(name); // 'Unknown'
Safe Navigation Operator
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();
Inventor tesla = new Inventor("Nikola Tesla", "Serbian");
tesla.setPlaceOfBirth(new PlaceOfBirth("Smiljan"));
String city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, tesla, String.class);
System.out.println(city); // Smiljan
tesla.setPlaceOfBirth(null);
city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, tesla, String.class);
System.out.println(city); // null - does not throw NullPointerException!!!
Collection Selection
List<Inventor> list = (List<Inventor>) parser.parseExpression(
"Members.?[Nationality == 'Serbian']").getValue(societyContext);
.^匹配第一个符合的,.$匹配最后一个符合的。
Collection Projection
用于Map。
// returns ['Smiljan', 'Idvor' ]
List placesOfBirth = (List)parser.parseExpression("Members.![placeOfBirth.city]");
Expression templating
String randomPhrase = parser.parseExpression(
"random number is #{T(java.lang.Math).random()}",
new TemplateParserContext()).getValue(String.class);
// evaluates to "random number is 0.7038186818312008"
TemplateParserContext定义:
public class TemplateParserContext implements ParserContext {
public String getExpressionPrefix() {
return "#{";
}
public String getExpressionSuffix() {
return "}";
}
public boolean isTemplate() {
return true;
}
}