spel 表达式
概念
Spring表达式语言全称为“Spring Expression Language”,缩写为“SpEL”,类似于Struts2x中使用的OGNL表达式语言,能在运行时构建复杂表达式、存取对象图属性、对象方法调用等等,并且能与Spring功能完美整合,如能用来配置Bean定义。
表达式语言给静态Java语言增加了动态功能。
SpEL是单独模块,只依赖于core模块,不依赖于其他模块,可以单独使用。
SpEL 支持如下表达式:
- 基本表达式: 字面量表达式、关系,逻辑与算数运算表达式、字符串连接及截取表达式、三目运算及Elivis表达式、正则表达式、括号优先级表达式;
- 类相关表达式: 类类型表达式、类实例化、instanceof表达式、变量定义及引用、赋值表达式、自定义函数、对象属性存取及安全导航表达式、对象方法调用、Bean引用;
- 集合相关表达式: 内联List、内联数组、集合,字典访问、列表,字典,数组修改、集合投影、集合选择;不支持多维内联数组初始化;不支持内联字典定义;
- 其他表达式:模板表达式。
注:SpEL表达式中的关键字是不区分大小写的。
基础
HelloWorld
首先创建一个 springboot 工程,添加springweb 依赖。
SpEL在求表达式值时一般分为四步,其中第三步可选:首先构造一个解析器,其次解析器解析字符串表达式,在此构造上下文,最后根据上下文得到表达式运算后的值。
@SpringBootTest
class SpelDemoApplicationTests {
@Test
public void test1() {
ExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression("('Hello' + ' World').concat(#end)");
EvaluationContext context = new StandardEvaluationContext();
context.setVariable("end", "!");
System.out.println(expression.getValue(context));
}
}
输出:
Hello World!
- 创建解析器:SpEL使用
ExpressionParser接口表示解析器,提供SpelExpressionParser默认实现; - 解析表达式:使用
ExpressionParser的parseExpression来解析相应的表达式为Expression对象。 - 构造上下文:准备比如变量定义等等表达式需要的上下文数据。
- 求值:通过Expression接口的getValue方法根据上下文获得表达式值。
获取类中的属性
首先创建一个 user 类。
public class User {
private Integer id;
private String username;
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
获取 user 类的 username 属性。
@Test
void test(){
// 这个表达式的含义表示调用user对象中的username属性
String exp = "#user.username";
SpelExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression(exp);
User user = new User();
user.setId(1);
user.setUsername("zxq");
user.setAddress("济南");
// 创建上下文环境并设置值
StandardEvaluationContext context = new StandardEvaluationContext();
context.setVariable("user",user);
String value = expression.getValue(context, String.class);
System.out.println("value = " + value);
}
expression.getValue:第一个参数是上下文对象,第二个参数是返回值的类型。
#user 要对应 context.setVariable 的第一个参数,表达式也可以不写#user 直接写要获取的属性,代码如下
@Test
void test2(){
// 这个表达式的含义表示调用user对象中的username属性
String exp = "username";
SpelExpressionParser parser = new SpelExpressionParser();
Expression expression = parser.parseExpression(exp);
User user = new User();
user.setId(1);
user.setUsername("zxq");
user.setAddress("济南");
// 创建上下文环境并设置值
StandardEvaluationContext context = new StandardEvaluationContext();
context.setRootObject(user);
String value = expression.getValue(context, String.class);
System.out.println("value = " + value);
}
此时在设置上下文是需要调用 context.setRootObject 将 user 设置为 RootObject,这样机会直接获取user 对象中的 username 属性。
调用类中的方法
public class UserService {
public String sayhello(String username){
return username;
}
}
@Test
void test3(){
String exp = "#us.sayhello(\"zxq\")";
SpelExpressionParser parser = new SpelExpressionParser();
// 解析
Expression expression = parser.parseExpression(exp);
// 创建上下文环境并设置值
StandardEvaluationContext context = new StandardEvaluationContext();
UserService us = new UserService();
context.setVariable("us",us);
String value = expression.getValue(context, String.class);
System.out.println("value = " + value);
}
同样也可以不写 #us。
@Test
void test3(){
String exp = "sayhello(\"zxq\")";
SpelExpressionParser parser = new SpelExpressionParser();
// 解析
Expression expression = parser.parseExpression(exp);
// 创建上下文环境并设置值
StandardEvaluationContext context = new StandardEvaluationContext();
UserService us = new UserService();
context.setRootObject(us);
String value = expression.getValue(context, String.class);
System.out.println("value = " + value);
}
Bean 引用
首先创建一个类,交给spring容器管理
@Service("bs")
public class BookService {
public String sayHello(){
return "这是一本好书";
}
}
@SpringBootTest
class SpelDemoApplicationTests {
@Autowired
BeanFactory beanFactory;
@Test
void test4(){
String exp = "@bs.sayHello()";
SpelExpressionParser parser = new SpelExpressionParser();
// 解析
Expression expression = parser.parseExpression(exp);
// 创建上下文环境并设置值
StandardEvaluationContext context = new StandardEvaluationContext();
context.setBeanResolver(new BeanFactoryResolver(beanFactory));
String value = expression.getValue(context, String.class);
System.out.println("value = " + value);
}
}
SpEL支持使用“@”符号来引用Bean,在引用Bean时需要使用BeanResolver接口实现来查找Bean,Spring提供BeanFactoryResolver实现。
@bs bs 为 Bean 的名称