SpEL表达式初体验

Lou.Chen2022年12月13日
大约 4 分钟

什么是SpEL

SpELSpring表达式语言Spring Expression Language

能在运行时构建复杂表达式、存取对象图属性、对象方法调用等等,并且能与Spring功能完美整合

所属依赖:org.springframework.expression

SpEL支持的表达式

  • 基本表达式: 字面量表达式、关系,逻辑与算数运算表达式、字符串连接及截取表达式、三目运算及Elivis表达式、正则表达式、括号优先级表达式;

  • 类相关表达式: 类类型表达式、类实例化、instanceof表达式、变量定义及引用、赋值表达式、自定义函数、对象属性存取及安全导航表达式、对象方法调用、Bean引用;

  • 集合相关表达式: 内联List、内联数组、集合,字典访问、列表,字典,数组修改、集合投影、集合选择;不支持多维内联数组初始化;不支持内联字典定义;

  • 其他表达式:模板表达式。

⚠️ SpEL表达式中的关键字是不区分大小写的。

SpEL简单使用

字面量表达式

    @Test
    void test1() {
        String str = "1+3";
        // spel解析表达式
        SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
        // 执行解析字符串
        Expression expression = spelExpressionParser.parseExpression(str);
        // 获取表达式执行结果
        Object value = expression.getValue();
        // 4
        System.out.println(value);
    }

获取对象属性

@Data
public class User {
    private String id;
    private String username;
    private String address;
}

使用 # 指定的名称从上下文环境中获取对象

    @Test
    void test2() {
        // 调用user对象中的username属性。 # 表示获取上下文环境中的变量名
        String str = "#user.username";
        // spel解析表达式
        SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
        // 执行解析字符串
        Expression expression = spelExpressionParser.parseExpression(str);
        // 设置上下文环境
        StandardEvaluationContext sec=new StandardEvaluationContext();
        // 构建对象
        User user=new User();
        user.setUsername("张三");
        // 将构建的对象设置到上下文环境中
        sec.setVariable("user",user );
        // 获取表达式执行结果  获取的属性必须要有getter方法,否则获取失败
        Object value = expression.getValue(sec);
        // 张三
        System.out.println(value);
    }

若不加 # 则从根对象中获取

    @Test
    void test3() {
        // 直接调用上下文环境中的根对象的username属性。
        String str = "username";
        // spel解析表达式
        SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
        // 执行解析字符串
        Expression expression = spelExpressionParser.parseExpression(str);
        // 设置上下文环境
        StandardEvaluationContext sec=new StandardEvaluationContext();
        // 构建对象
        User user=new User();
        user.setUsername("张三");
        // 将构建的对象设置为上下文环境中的根对象。根对象只能有一个
        sec.setRootObject(user );
        // 获取表达式执行结果  获取的属性必须要有getter方法,否则获取失败
        Object value = expression.getValue(sec);
        // 张三
        System.out.println(value);
    }

获取对象的方法结果

public class UserService {

    public String getUserName() {
        return "zhangsan";
    }
    public String getUserName(String username) {
        return username;
    }
}

# 指定名称从上下文环境获取指定对象 . 后面为对象的方法

@Test
void test5() {
    // 直接调用上下文环境中的指定变量 getUserName 方法。
    String str = "#us.getUserName()";

    // 直接调用上下文环境中的指定变量 getUserName 方法并传入 hello 参数
    // String str = "#us.getUserName('hello')";

    // spel解析表达式
    SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
    // 执行解析字符串
    Expression expression = spelExpressionParser.parseExpression(str);
    // 设置上下文环境
    StandardEvaluationContext sec=new StandardEvaluationContext();
    // 构建对象
    UserService userService=new UserService();
    // 将构建的对象设置为上下文环境中的变量
    sec.setVariable("us",userService);
    // 获取表达式执行结果
    Object value = expression.getValue(sec);
    System.out.println(value);
}

不加 # 则代表直接从上下文环境中的根对象获取

    @Test
    void test4() {
        // 直接调用上下文环境中的根对象的 getUserName 方法。
        // String str = "getUserName()";

        // 直接调用上下文环境中的根对象的 getUserName 方法并传入 hello 参数
        String str = "getUserName('hello')";

        // spel解析表达式
        SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
        // 执行解析字符串
        Expression expression = spelExpressionParser.parseExpression(str);
        // 设置上下文环境
        StandardEvaluationContext sec=new StandardEvaluationContext();
        // 构建对象
        UserService userService=new UserService();
        // 将构建的对象设置为上下文环境中的根对象。根对象只能有一个
        sec.setRootObject(userService);
        // 获取表达式执行结果
        Object value = expression.getValue(sec);
        System.out.println(value);
    }

获取容器中实例指定的方法

@Service("as")
public class AccountService {
    public String selectAccount() {
        return "1001";
    }
}

@ 代表Spring容器中实例的别名

    @Autowired
    BeanFactory beanFactory;
    @Test
    void test6() {
        // 执行Spring容器中bean名称为 as 的 selectAccount 方法
        String str = "@as.selectAccount()";
        // spel解析表达式
        SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
        // 执行解析字符串
        Expression expression = spelExpressionParser.parseExpression(str);
        // 设置上下文环境
        StandardEvaluationContext sec=new StandardEvaluationContext();
        // 设置Bean解析器
        sec.setBeanResolver(new BeanFactoryResolver(beanFactory));
        // 获取表达式执行结果
        Object value = expression.getValue(sec);
        System.out.println(value);
    }