专栏名称: 芋道源码
纯 Java 源码分享公众号,目前有「Dubbo」「SpringCloud」「Java 并发」「RocketMQ」「Sharding-JDBC」「MyCAT」「Elastic-Job」「SkyWalking」「Spring」等等
目录
相关文章推荐
芋道源码  ·  彻底告别 ... ·  2 天前  
芋道源码  ·  线上问题排查指南 ·  4 天前  
Java编程精选  ·  巧用 SpringEvent 解决 ... ·  6 天前  
芋道源码  ·  11月跳槽的兄弟注意了。。 ·  6 天前  
51好读  ›  专栏  ›  芋道源码

玩转Spring:强大的 SpEL 表达式

芋道源码  · 公众号  · Java  · 2024-11-16 16:47

正文

👉 这是一个或许对你有用的社群

🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入芋道快速开发平台知识星球。下面是星球提供的部分资料: 

👉这是一个或许对你有用的开源项目

国产 Star 破 10w+ 的开源项目,前端包括管理后台 + 微信小程序,后端支持单体和微服务架构。

功能涵盖 RBAC 权限、SaaS 多租户、数据权限、商城、支付、工作流、大屏报表、微信公众号、CRM 等等功能:

  • Boot 仓库:https://gitee.com/zhijiantianya/ruoyi-vue-pro
  • Cloud 仓库:https://gitee.com/zhijiantianya/yudao-cloud
  • 视频教程:https://doc.iocoder.cn
【国内首批】支持 JDK 21 + SpringBoot 3.2.2、JDK 8 + Spring Boot 2.7.18 双版本 

来源:juejin.cn/post
/7326049852344696843


本文概览

欢迎阅读本文,其中我们将深入探讨 Spring Expression Language(SpEL)的语法和实际应用。从基础概念到高级用法,我们将在本文中了解如何使用 SpEL 提高代码的灵活性和表达力。

无论大家是初学者还是有经验的开发者,本文将为大家提供深入了解 SpEL 的机会,使大家能够在 Spring 项目中更好地利用这一强大的表达式语言。

文章涉及到的示例代码:

https://github.com/markuszcl99/guide-spring

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 视频教程:https://doc.iocoder.cn/video/

语法详解

字面量表达式

SpEL 支持以下字面量表达式:

  • 字符串 (String)
  • 数值: 整数 int or long 类型,十六进制 int or long 类型以及浮点类型 float or double
  • 布尔值: true or false
  • 空对象 : null

示例:

package com.markus.spring.expression.language.reference;

import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;

/**
 * @author: markus
 * @date: 2024/1/21 8:46 PM
 * @Description:
 * @Blog: https://markuszhang.com
 * It's my honor to share what I've learned with you!
 */

public class LiteralExpressions {
    public static void main(String[] args) {
        ExpressionParser parser = new SpelExpressionParser();
        // 解析 字符串
        String value = parser.parseExpression("'Hello,Literal Expression'").getValue(String.class);
        System.out.println(value);
        // 解析 数值 int long float double
        double number = parser.parseExpression("4.5").getValue(double.class);
        System.out.println(number);
        // 解析 布尔值 true or false
        boolean bool = parser.parseExpression("true").getValue(boolean.class);
        System.out.println(bool);
        // 解析 空对象 null
        Object obj = parser.parseExpression("null").getValue();
        System.out.println(obj);
    }
}

执行结果:

属性表达式

在 SpEL 表达式中,我们可以通过 属性名 来获取对应路径的内容,如果涉及到嵌套属性,我们用 '.' 来表示级联关系。

示例:

package com.markus.spring.expression.language.reference;

import com.markus.spring.expression.language.Inventor;
import com.markus.spring.expression.language.InventorBuilder;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

/**
 * @author: markus
 * @date: 2024/1/21 8:59 PM
 * @Description:
 * @Blog: https://markuszhang.com
 * It's my honor to share what I've learned with you!
 */

public class PropertiesExpression {
    public static void main(String[] args) {
        Inventor inventor = InventorBuilder.builder();

        EvaluationContext context = new StandardEvaluationContext(inventor);

        ExpressionParser parser = new SpelExpressionParser();
        String name = parser.parseExpression("name").getValue(context, String.class);
        System.out.println(name);

        // nested property
        int length = parser.parseExpression("name.length").getValue(context, int.class);
        System.out.println(length);
    }
}

执行结果:

容器表达式

这里的容器用于表示 数组(Array)、集合(List)、字典(Map),我们统一来看下有关于这些内容的 SpEL 表达式都有哪些

Array

  • 索引获取,通过方括号[index]来获取目标索引值
  • 数组构造,包括基本类型构造、复杂类型构造

示例:

package com.markus.spring.expression.language.reference;

import com.markus.spring.expression.language.Inventor;
import com.markus.spring.expression.language.InventorBuilder;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.util.Arrays;

/**
 * @author: markus
 * @date: 2024/1/21 9:10 PM
 * @Description: 数组相关的表达式示例
 * @Blog: https://markuszhang.com
 * It's my honor to share what I've learned with you!
 */

public class ArraysExpression {
    public static void main(String[] args) {
        ExpressionParser parser = new SpelExpressionParser();

        // array
        Inventor[] inventors = {InventorBuilder.builder()};
        EvaluationContext context = new StandardEvaluationContext(inventors);

        // index 表达
        Inventor inventor = parser.parseExpression("[0]").getValue(context, Inventor.class);
        System.out.println(inventor);

        // index + nested property
        String name = parser.parseExpression("[0].name").getValue(context, String.class);
        System.out.println(name);

        // index + nested property index
        inventor.getBooleans().add(true);
        boolean bool = parser.parseExpression("[0].booleans[0]").getValue(context, boolean.class);
        System.out.println(bool);

        // array construction
        int[] numbers = parser.parseExpression("new int[]{1,2,3}").getValue(context, int[].class);
        for (int number : numbers) {
            System.out.print(number + " ");
        }
        System.out.println();

        // complex type arrays constructor
        Inventor[] complexTypeArrays = parser
                .parseExpression("new com.markus.spring.expression.language.Inventor[1]")
                .getValue(context, Inventor[].class);
        complexTypeArrays[0] = InventorBuilder.builder();
        Arrays.stream(complexTypeArrays).forEach(System.out::println);
    }
}

List

集合和数组的数据访问以及嵌套属性访问的方式一致,示例可以参考 Array 实现。我们额外补充些有关 List 的示例

package com.markus.spring.expression.language.reference;

import com.markus.spring.expression.language.Inventor;
import com.markus.spring.expression.language.InventorBuilder;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.util.ArrayList;
import java.util.List;

/**
 * @author: markus
 * @date: 2024/1/21 9:32 PM
 * @Description: List 集合有关 SpEL 表达式的示例
 * @Blog: https://markuszhang.com
 * It's my honor to share what I've learned with you!
 */

public class ListExpression {
    public static void main(String[] args) {
        Inventor inventor = InventorBuilder.builder();
        List inventors = new ArrayList<>();
        inventors.add(inventor);
        EvaluationContext context = new StandardEvaluationContext(inventors);

        ExpressionParser parser = new SpelExpressionParser();
        // by [index] get element
        Inventor inventorFromParser = parser.parseExpression("[0]").getValue(context, Inventor.class);
        System.out.println(inventorFromParser);

        // inline list
        // 1. simple type
        @SuppressWarnings("unchecked")
        List integers = parser.parseExpression("{1,2,3,4,5}").getValue(context, List.class);
        System.out.println(integers);
        // 2. complex type
        @SuppressWarnings("unchecked")
        List inventorList = (List) parser.parseExpression("{T(com.markus.spring.expression.language.InventorBuilder).builder()}").getValue(context);
        System.out.println(inventorList);
    }
}

执行结果:

Map

Map中的数据访问有些不同,示例如下所示:

package com.markus.spring.expression.language.reference;

import com.markus.spring.expression.language.Inventor;
import com.markus.spring.expression.language.InventorBuilder;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author: markus
 * @date: 2024/1/21 9:47 PM
 * @Description:
 * @Blog: https://markuszhang.com
 * It's my honor to share what I've learned with you!
 */

public class MapExpression {
    public static void main(String[] args) {
        Inventor inventor = InventorBuilder.builder();
        Map map = new HashMap();
        map.put("markus", inventor);
        EvaluationContext context = new StandardEvaluationContext(map);

        ExpressionParser parser = new SpelExpressionParser();
        // by ['key'] get element
        Inventor inventorFromParser = parser.parseExpression("['markus']").getValue(context, Inventor.class);
        System.out.println(inventorFromParser);

        // nested property access
        String name = parser.parseExpression("['markus'].name").getValue(context, String.class);
        System.out.println(name);

        // inline map
        @SuppressWarnings("unchecked")
        Map inventorMap = parser
                .parseExpression("{'markus':T(com.markus.spring.expression.language.InventorBuilder).builder()}")
                .getValue(context, Map.class);
        System.out.println(inventorMap);

    }
}

执行结果:

方法调用表达式

示例如下:

package com.markus.spring.expression.language.reference;

import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;

/**
 * @author: markus
 * @date: 2024/1/21 9:55 PM
 * @Description: 方法调用表达式的示例
 * @Blog: https://markuszhang.com
 * It's my honor to share what I've learned with you!
 */

public class MethodInvokeExpression {
    public static void main(String[] args) {
        ExpressionParser parser = new SpelExpressionParser();
        String subString = parser.parseExpression("'Hello,SpEL'.substring(0,5)").getValue(String.class);
        System.out.println(subString);
    }
}

执行结果:

运算符表达式

SpEL 表达式支持如下运算法:

  • 关系运算符
  • 逻辑运算符
  • 算术运算符
  • 赋值运算符

示例如下:

package com.markus.spring.expression.language.reference;

import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;

/**
 * @author: markus
 * @date: 2024/1/21 10:00 PM
 * @Description: 运算符 SpEL 示例
 * @Blog: https://markuszhang.com
 * It's my honor to share what I've learned with you!
 */

public class OperatorsExpression {
    /**
     * more demo please reference https://docs.spring.io/spring-framework/reference/core/expressions/language-ref/operators.html
     *
     * @param args
     */

    public static void main(String[] args) {

        ExpressionParser parser = new SpelExpressionParser();
        // first : relational operators
        boolean result = parser.parseExpression("2 ).getValue(Boolean.class);
        System.out.println("2  + result);

        result = parser.parseExpression("2 == 5").getValue(Boolean.class);
        System.out.println("2 == 5 : " + result);

        result = parser.parseExpression("1 instanceof T(int)").getValue(Boolean.class);
        System.out.println("1 instanceof T(int) : " + result);
        result = parser.parseExpression("1 instanceof T(Integer)").getValue(Boolean.class);
        System.out.println("1 instanceof T(Integer) : " + result);

        // second : logical operators
        // and (&&)
        // or (||)
        // not (!)
        result = parser.parseExpression("true or false").getValue(Boolean.class);
        System.out.println("true or false : " + result);
        result = parser.parseExpression("true and false").getValue(Boolean.class);
        System.out.println("true and false : " + result);
        result = parser.parseExpression("!true").getValue(Boolean.class);
        System.out.println("!true : " + result);

        // third : mathematical operators
        // + - * / %
        // Addition
        int two = parser.parseExpression("1 + 1").getValue(Integer.class);  // 2
        System.out.println("1 + 1 : " + two);
        String testString = parser.parseExpression(
                "'test' + ' ' + 'string'").getValue(String.class);  // 'test string'
        System.out.println("'test' + ' ' + 'string' : " + testString);
        // Subtraction
        int four = parser.parseExpression("1 - -3").getValue(Integer.class);  // 4
        System.out.println("1 - -3 : " + four);
        double d = parser.parseExpression("1000.00 - 1e4").getValue(Double.class);  // -9000
        System.out.println("1000.00 - 1e4 : " + d);
        // Multiplication
        int six = parser.parseExpression("-2 * -3").getValue(Integer.class);  // 6
        System.out.println("-2 * -3 : " + six);
        double twentyFour = parser.parseExpression("2.0 * 3e0 * 4").getValue(Double.class);  // 24.0
        System.out.println("2.0 * 3e0 * 4 : " + twentyFour);
        // Division
        int minusTwo = parser.parseExpression("6 / -3").getValue(Integer.class);  // -2
        System.out.println("6 / -3 : " + minusTwo);
        double oneD = parser.parseExpression("8.0 / 4e0 / 2").getValue(Double.class);  // 1.0
        System.out.println("8.0 / 4e0 / 2 : " + oneD);
        // Modulus
        int three = parser.parseExpression("7 % 4").getValue(Integer.class);  // 3
        System.out.println("7 % 4 : " + three);
        int one = parser.parseExpression("8 / 5 % 2").getValue(Integer.class);  // 1
        System.out.println("8 / 5 % 2 : " + one);
        // Operator precedence
        int minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Integer.class);  // -21
        System.out.println("1+2-3*8 : " + minusTwentyOne);
    }
}

执行结果:

类型表达式

我们可以通过 T(xxx) 来表示 Class 的实例,静态方法也可以通过这个方式使用,前面我们已经展示过,即 T(xxx).method(xxx),另外值得注意的是,在java.lang包下的类可以不指定全限定名,直接指定类名。

示例如下:

package com.markus.spring.expression.language.reference;

import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;

/**
 * @author: markus
 * @date: 2024/1/21 10:25 PM
 * @Description: 类型 相关的 SpEL 示例
 * @Blog: https://markuszhang.com
 * It's my honor to share what I've learned with you!
 */

public class TypeExpression {
    public static void main(String[] args) {
        ExpressionParser parser = new SpelExpressionParser();
        Class dateClass = parser.parseExpression("T(java.util.Date)").getValue(Class.class);
        System.out.println(dateClass);

        Class stringClass = parser.parseExpression("T(String)").getValue(Class.class);
        System.out.println(stringClass);

        boolean trueValue = parser.parseExpression(
                        "T(java.math.RoundingMode).CEILING )
                .getValue(Boolean.class);
        System.out.println(trueValue);
    }
}

执行结果:

构造器表达式

通过 SpEL 来初始化实例,使用时必须要指定全限定名(包括 java.lang 包下的)

示例如下:

package com.markus.spring.expression.language.reference;

import com.markus.spring.expression.language.Inventor;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;

/**
 * @author: markus
 * @date: 2024/1/21 10:31 PM
 * @Description: 构造器 SpEL 示例
 * @Blog: https://markuszhang.com
 * It's my honor to share what I've learned with you!
 */

public class ConstructorExpression {
    public static void main(String[] args) {
        ExpressionParser parser = new SpelExpressionParser();
        Inventor einstein = parser.parseExpression(
                        "new com.markus.spring.expression.language.Inventor()")
                .getValue(Inventor.class);
        System.out.println(einstein);
    }
}

执行结果:

变量表达式

我们可以在 SpEL 中通过使用 #variableName 来获取执行的变量值。另外 变量的表示形式必须按照以下要求(至少有以下1个组成):

  • A-Za-z
  • 0-9
  • _
  • $

示例如下:

package com.markus.spring.expression.language.reference;

import com.markus.spring.expression.language.Inventor;
import com.markus.spring.expression.language.InventorBuilder;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.util.ArrayList;
import java.util.List;

/**
 * @author: markus
 * @date: 2024/1/21 10:35 PM
 * @Description: 变量 SpEL 表达式示例
 * @Blog: https://markuszhang.com
 * It's my honor to share what I've learned with you!
 */

public class VariableExpression {
    public static void main(String[] args) {
        Inventor inventor = InventorBuilder.builder();
        inventor.getBooleans().add(true);
        inventor.getBooleans().add(false);

        EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();
        context.setVariable("newName""Luna");

        ExpressionParser parser = new SpelExpressionParser();
        parser.parseExpression("name = #newName").getValue(context, inventor);
        System.out.println(inventor);

        // #this and #root
        // #this 总是指向当前表达式中计算的对象
        // #root 总是指向根对象

        List integers = new ArrayList<>();
        integers.add(1);
        integers.add(2);
        integers.add(3);
        integers.add(4);
        integers.add(5);
        integers.add(6);
        context.setVariable("integers", integers);
        String thisExpression = "#integers.?[#this > 3]";
        @SuppressWarnings("unchecked")
        List gt3List = parser.parseExpression(thisExpression).getValue(context, List.class);
        gt3List.forEach(integer -> System.out.print(integer + " "));
        System.out.println();

        // #root
        context = new StandardEvaluationContext(inventor);
        Inventor value = parser.parseExpression("#root").getValue(context, Inventor.class);
        System.out.println(value);
    }
}

执行结果:

执行结果:

Bean 引用表达式

通过 @xxx 来获取 Spring 容器中的 Bean 实例

示例如下:

package com.markus.spring.expression.language.reference;

import com.markus.spring.expression.language.Inventor;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

/**
 * @author: markus
 * @date: 2024/1/21 11:00 PM
 * @Description: Bean 应用示例
 * @Blog: https://markuszhang.com
 * It's my honor to share what I've learned with you!
 */

public class BeanReferenceExpression {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:/META-INF/expression-in-bean-definitions.xml");

        BeanFactoryResolver beanFactoryResolver = new BeanFactoryResolver(context.getBeanFactory());
        StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
        evaluationContext.setBeanResolver(beanFactoryResolver);

        ExpressionParser parser = new SpelExpressionParser();
        String expression = "@inventor";
        Inventor inventor = parser.parseExpression(expression).getValue(evaluationContext, Inventor.class);
        System.out.println(inventor);
    }
}

执行结果:

三元表达式

我们还可以在表达式内部使用三元运算符执行if-then-else条件逻辑。

package com.markus.spring.expression.language.reference;

import com.markus.spring.expression.language.Inventor;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;

/**
 * @author: markus
 * @date: 2024/1/21 11:07 PM
 * @Description: 三元表达式 示例
 * @Blog: https://markuszhang.com
 * It's my honor to share what I've learned with you!
 */

public class TernaryOperatorExpression {
    public static void main(String[] args) {
        ExpressionParser parser = new SpelExpressionParser();
        String falseString = parser.parseExpression(
                "false ? 'trueExp' : 'falseExp'").getValue(String.class);
        System.out.println("false ? 'trueExp' : 'falseExp' : " + falseString);

        // The Elvis operator (精简版 三元表达式)
        String name = parser.parseExpression("name?:'Unknown'").getValue(new Inventor(), String.class);
        System.out.println(name);  // 'Unknown'
    }
}

执行结果:

安全指针表达式

为避免出现空指针,我们还可以在 SpEL 中使用 ?.来实现

示例如下:

package com.markus.spring.expression.language.reference;

import com.markus.spring.expression.language.Inventor;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.SimpleEvaluationContext;

/**
 * @author: markus
 * @date: 2024/1/21 11:11 PM
 * @Description: 安全指针示例
 * @Blog: https://markuszhang.com
 * It's my honor to share what I've learned with you!
 */

public class SafeNavigationOperators {
    public static void main(String[] args) {
        ExpressionParser parser = new SpelExpressionParser();
        EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();

        Inventor inventor = new Inventor();
        inventor.setName("markus zhang");
        context.setVariable("inventor", inventor);

        String name = parser.parseExpression("#inventor.name?.#inventor.name").getValue(context, String.class);
        System.out.println(name);  // markus zhang

        inventor.setName(null);
        name = parser.parseExpression("#inventor.name?.#inventor.name").getValue(context, String.class);
        System.out.println(name);  // null - does not throw NullPointerException!!!
    }
}

执行结果:

集合筛选表达式

Selection是一种强大的表达语言功能,它允许您通过从其条目中进行选择,将源集合转换为另一个集合。选择使用的语法是.?[selectionExpression]。它过滤集合并返回一个包含原始元素子集的新集合。

示例如下:

package com.markus.spring.expression.language.reference;

import com.markus.spring.expression.language.Inventor;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.util.ArrayList;
import java.util.List;

/**
 * @author: markus
 * @date: 2024/1/21 11:17 PM
 * @Description: 集合元素选择 示例
 * @Blog: https://markuszhang.com
 * It's my honor to share what I've learned with you!
 */

public class CollectionSelectionExpression {
    public static void main(String[] args) {
        EvaluationContext context = new StandardEvaluationContext();
        List integers = new ArrayList<>();
        integers.add(1);
        integers.add(2);
        integers.add(3);
        integers.add(4);
        integers.add(5);
        integers.add(6);
        context.setVariable("integers", integers);

        ExpressionParser parser = new SpelExpressionParser();
        @SuppressWarnings("unchecked")
        List list = (List) parser.parseExpression(
                "#integers.?[#this == 3 || #this == 4]").getValue(context);
        list.forEach(ele -> {
            System.out.print(ele + " ");
        });
    }
}

执行结果:

集合子集表达式

集合子集 意为 获取目标集合中某一字段集合,示例如下:

package com.markus.spring.expression.language.reference;

import com.markus.spring.expression.language.Inventor;
import com.markus.spring.expression.language.InventorBuilder;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.util.ArrayList;
import java.util.List;

/**
 * @author: markus
 * @date: 2024/1/21 11:17 PM
 * @Description: 集合元素选择 示例
 * @Blog: https://markuszhang.com
 * It's my honor to share what I've learned with you!
 */

public class CollectionProjectionExpression {
    public static void main(String[] args) {
        EvaluationContext context = new StandardEvaluationContext();
        List inventors = new ArrayList<>();
        inventors.add(InventorBuilder.builder());
        inventors.add(InventorBuilder.builder("Luna"));
        context.setVariable("inventors", inventors);

        ExpressionParser parser = new SpelExpressionParser();
        @SuppressWarnings("unchecked")
        List list = (List) parser.parseExpression(
                "#inventors.![name]").getValue(context);
        list.forEach(ele -> {
            System.out.println(ele + " ");
        });
    }
}

执行结果:

模板表达式

表达式执行一个模板,并在这个模板中通过 #{} 来占位,示例如下:

package com.markus.spring.expression.language.reference;

import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;

/**
 * @author: markus
 * @date: 2024/1/21 11:29 PM
 * @Description:
 * @Blog: https://markuszhang.com
 * It's my honor to share what I've learned with you!
 */

public class TemplateExpression {
    public static void main(String[] args) {

        ExpressionParser parser = new SpelExpressionParser();

        String randomPhrase = parser.parseExpression(
                "random number is #{T(java.lang.Math).random()}",
                new TemplateParserContext()).getValue(String.class);
        System.out.println("random number is #{T(java.lang.Math).random()} : " + randomPhrase);
    }

    public static class TemplateParserContext implements ParserContext {

        public String getExpressionPrefix() {
            return "#{";
        }

        public String getExpressionSuffix() {
            return "}";
        }

        public boolean isTemplate() {
            return true;
        }
    }
}

执行结果:

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud
  • 视频教程:https://doc.iocoder.cn/video/

本文总结

通过本文,我们详细讨论了 SpEL 的语法、特性和应用场景。从简单的字面量表达式到复杂的类型引用,相信大家已经掌握了在 Spring 项目中灵活使用 SpEL 的关键知识。

在总结中,不要忘记不断实践和深入研究,以便更好地运用 SpEL 提高代码的可读性和可维护性。感谢您的阅读,希望大家在今后的项目中充分发挥 SpEL 的潜力!



欢迎加入我的知识星球,全面提升技术能力。

👉 加入方式,长按”或“扫描”下方二维码噢

星球的内容包括:项目实战、面试招聘、源码解析、学习路线。

文章有帮助的话,在看,转发吧。

谢谢支持哟 (*^__^*)