从多个方面详解Spring表达式

发布时间:2023-05-18

一、什么是Spring表达式

Spring表达式,又称为SpEL(Sprig Expression Language),是Spring Framework中专门用来进行计算和属性取值的表达式语言。SpEL的功能十分强大,支持调用方法、进行正则表达式匹配等复杂操作,并且可以与Spring IoC容器、Spring AOP等其他功能一起使用。

二、SpEL的语法

SpEL的语法比较简单,常用的操作符有加减乘除、逻辑运算符、比较运算符等。SpEL的语法主要由三个部分组成,分别是:属性、方法和表达式。

  1. 属性:SpEL可以直接访问JavaBean的属性,示例代码如下:
public class Person {
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}
// 获取Person实例中的属性值
Person person = new Person();
person.setName("Tom");
person.setAge(18);
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("name");
String name = (String) exp.getValue(person); // name值为Tom
  1. 方法:SpEL中可以调用JavaBean中的方法,示例代码如下:
public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }
    public int subtract(int a, int b) {
        return a - b;
    }
}
// 调用Calculator中的add方法
Calculator calculator = new Calculator();
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("add(1,2)");
int result = (Integer) exp.getValue(calculator); // result值为3
  1. 表达式:SpEL中可以使用各种运算符进行复杂的运算,示例代码如下:
ExpressionParser parser = new SpelExpressionParser();
// 计算 1+2+3+4+5
Expression exp = parser.parseExpression("1+2+3+4+5");
int result1 = (Integer) exp.getValue(); // result1值为15
// 将字符串转换为大写形式
Expression exp2 = parser.parseExpression("'hello'.toUpperCase()");
String result2 = (String) exp2.getValue(); // result2值为"HELLO"
// 判断整数num的值是否大于0
int num = -1;
Expression exp3 = parser.parseExpression("num > 0");
boolean result3 = (Boolean) exp3.getValue(); // result3值为false

三、变量和上下文

SpEL提供了两种类型的变量,分别是根对象和上下文变量。根对象可以通过设置EvaluationContext中的rootObject属性来设置;上下文变量可以通过setVariable方法来设置。示例代码如下:

// 计算person对象中name属性的长度
Person person = new Person();
person.setName("Tom");
EvaluationContext context = new StandardEvaluationContext(person);
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("name.length()");
int result1 = (Integer) exp.getValue(context); // result1值为3
// 计算num是否在min和max之间
StandardEvaluationContext context = new StandardEvaluationContext();
context.setVariable("min", 1);
context.setVariable("max", 10);
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("num > min and num < max");
boolean result2 = (Boolean) exp.getValue(context); // result2值为false

四、SpEL与Spring IoC容器的整合

SpEL可以与Spring IoC容器无缝整合,可以使用SpEL表达式来进行Bean的注入等操作。示例代码如下:

<!-- 在XML配置文件中使用SpEL进行属性值注入 -->
<bean id="person" class="com.example.Person">
    <property name="name" value="#{systemProperties['user.name']}" />
    <property name="age" value="#{ T(Integer).parseInt('${person.age}') }" />
</bean>
// 在JavaConfig中使用SpEL进行属性值注入
@Configuration
public class AppConfig {
    @Value("#{ systemProperties['os.name'] }")
    private String osName;
    @Bean
    public Person person() {
        Person person = new Person();
        person.setName("Tom");
        person.setAge(#{ T(Integer).parseInt('${person.age}') });
        return person;
    }
}

五、SpEL的高级应用

除了上述常见的用法外,SpEL还可以进行正则表达式匹配、集合过滤、集合投影等高级操作。示例代码如下:

// 进行正则表达式匹配
String email = "example@test.com";
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression("'example@test.com'.matches('[a-z]+@[a-z]+\\.[a-z]+')");
boolean result1 = (Boolean) exp.getValue(); // result1值为true
// 对集合进行过滤和投影
List<Person> personList = new ArrayList<>();
Person p1 = new Person();
p1.setName("Tom");
p1.setAge(18);
Person p2 = new Person();
p2.setName("Jerry");
p2.setAge(20);
Person p3 = new Person();
p3.setName("Alice");
p3.setAge(22);
personList.add(p1);
personList.add(p2);
personList.add(p3);
EvaluationContext context = new StandardEvaluationContext();
context.setVariable("personList", personList);
ExpressionParser parser = new SpelExpressionParser();
Expression exp1 = parser.parseExpression("#personList.?[age > 19]"); // 过滤年龄大于19岁的Person
List<Person> result2 = (List<Person>) exp1.getValue(context); // result2值为[p2, p3]
Expression exp2 = parser.parseExpression("#personList.![name]"); // 投影出三个Person的name属性,返回一个List
List<String> result3 = (List<String>) exp2.getValue(context); // result3值为["Tom", "Jerry", "Alice"]