阅读spel文档
This commit is contained in:
180
spring/spring boot/spel.md
Normal file
180
spring/spring boot/spel.md
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
# Spel
|
||||||
|
## Spel表达式计算
|
||||||
|
### 示例
|
||||||
|
如下是一个Spel表达式计算示例:
|
||||||
|
```java
|
||||||
|
ExpressionParser parser = new SpelExpressionParser();
|
||||||
|
Expression exp = parser.parseExpression("'Hello World'");
|
||||||
|
String message = (String) exp.getValue();
|
||||||
|
// 最终message计算的值是'Hello World'
|
||||||
|
```
|
||||||
|
### Concept
|
||||||
|
`ExpressionParser`接口用于对表达式字符串进行解析,在上述示例中,表达式字符串是一个由单引号包围起来的字符串字面量。
|
||||||
|
|
||||||
|
`Expression`接口则是负责对表达式字符串进行计算。
|
||||||
|
|
||||||
|
在调用`parser.parseExpression`和`exp.getValue`,分别会抛出`ParseException`和`EvaluationException`异常。
|
||||||
|
|
||||||
|
Spel支持许多特性,例如调用方法,访问属性,调用构造方法等,示例如下:
|
||||||
|
|
||||||
|
#### 调用方法
|
||||||
|
```java
|
||||||
|
ExpressionParser parser = new SpelExpressionParser();
|
||||||
|
Expression exp = parser.parseExpression("'Hello World'.concat('!')");
|
||||||
|
String message = (String) exp.getValue();
|
||||||
|
// message值为Hello World!
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 调用属性
|
||||||
|
```java
|
||||||
|
ExpressionParser parser = new SpelExpressionParser();
|
||||||
|
|
||||||
|
// invokes 'getBytes().length'
|
||||||
|
Expression exp = parser.parseExpression("'Hello World'.bytes.length");
|
||||||
|
int length = (Integer) exp.getValue();
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 调用构造器
|
||||||
|
```java
|
||||||
|
ExpressionParser parser = new SpelExpressionParser();
|
||||||
|
Expression exp = parser.parseExpression("new String('hello world').toUpperCase()");
|
||||||
|
String message = exp.getValue(String.class);
|
||||||
|
```
|
||||||
|
|
||||||
|
通过`public <T> T getValue(Class<T> desiredResultType)`方法,向getValue方法传递一个Class对象,可以避免在调用getValue方法调用之后需要将返回值手动转化为特定类型。如果类型转化失败,会抛出一个EvaluationException异常。
|
||||||
|
|
||||||
|
#### 在特定对象上计算表达式
|
||||||
|
Spel支持在一个特定的对象上(该对象通常被称作root object)进行计算,例如如下示例:
|
||||||
|
```java
|
||||||
|
// 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
|
||||||
|
EvalutaionContext用于给表达式提供一个执行的上下文环境,通过EvalutaionContext,可以向context中放置一个变量,并且在后续中使用该变量:
|
||||||
|
```java
|
||||||
|
// 向context中放入一个list变量
|
||||||
|
ctx.setVariable("list",list)
|
||||||
|
|
||||||
|
// 在后续表达式中即可使用放入的list变量
|
||||||
|
// 获取放入context中的list变量的值
|
||||||
|
parser.parseExpression("#list[0]").getValue(ctx);
|
||||||
|
// 设置context中list变量的值
|
||||||
|
parser.parseExpression("#list[0]").setValue(ctx , "false");
|
||||||
|
```
|
||||||
|
#### EvaluationContext实现类
|
||||||
|
- SimpleEvaluationContext:实现了Spel语言的部分特性
|
||||||
|
- StandardEvaluationContext:实现了Spel语言的全部特性
|
||||||
|
|
||||||
|
### TypeConversion
|
||||||
|
默认情况下,spel会使用`org.springframework.core.convert.ConversionService`中的Conversion Service。该conversion service包含内置的类型转换,并且可以为类型之间指定自定义的类型转换。该转换是支持泛型的。
|
||||||
|
|
||||||
|
如下为支持泛型的示例:
|
||||||
|
```java
|
||||||
|
class Simple {
|
||||||
|
public List<Boolean> booleanList = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 在定义Bean对象时使用Spel表达式
|
||||||
|
可以通过@Value注解来为bean对象的域、方法参数、构造器参数指定默认值。通过如下方式来指定表达式:
|
||||||
|
- `#{ <expression string> }.`
|
||||||
|
|
||||||
|
#### 为field指定默认值
|
||||||
|
```java
|
||||||
|
public class FieldValueTestBean {
|
||||||
|
|
||||||
|
@Value("#{ systemProperties['user.region'] }")
|
||||||
|
private String defaultLocale;
|
||||||
|
|
||||||
|
public void setDefaultLocale(String defaultLocale) {
|
||||||
|
this.defaultLocale = defaultLocale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDefaultLocale() {
|
||||||
|
return this.defaultLocale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 通过setter为field指定默认值
|
||||||
|
```java
|
||||||
|
public class PropertyValueTestBean {
|
||||||
|
|
||||||
|
private String defaultLocale;
|
||||||
|
|
||||||
|
@Value("#{ systemProperties['user.region'] }")
|
||||||
|
public void setDefaultLocale(String defaultLocale) {
|
||||||
|
this.defaultLocale = defaultLocale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDefaultLocale() {
|
||||||
|
return this.defaultLocale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
#### @Autowired方法和构造器
|
||||||
|
@Autowired方法和构造器可以使用@Value注解为参数指定默认值:
|
||||||
|
```java
|
||||||
|
public class SimpleMovieLister {
|
||||||
|
|
||||||
|
private MovieFinder movieFinder;
|
||||||
|
private String defaultLocale;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
public void configure(MovieFinder movieFinder,
|
||||||
|
@Value("#{ systemProperties['user.region'] }") String defaultLocale) {
|
||||||
|
this.movieFinder = movieFinder;
|
||||||
|
this.defaultLocale = defaultLocale;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```java
|
||||||
|
public class MovieRecommender {
|
||||||
|
|
||||||
|
private String defaultLocale;
|
||||||
|
|
||||||
|
private CustomerPreferenceDao customerPreferenceDao;
|
||||||
|
|
||||||
|
public MovieRecommender(CustomerPreferenceDao customerPreferenceDao,
|
||||||
|
@Value("#{systemProperties['user.country']}") String defaultLocale) {
|
||||||
|
this.customerPreferenceDao = customerPreferenceDao;
|
||||||
|
this.defaultLocale = defaultLocale;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user