SpEL表达式详解

这篇具有很好参考价值的文章主要介绍了SpEL表达式详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、概述

中文spring官网:https://itmyhome.com/spring/expressions.html
英文spring官网:https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#expressions

Spring Expression Language(简称SpEL)是一种功能强大的表达式语言,是spring提供的,该语言类似于JSP当中的EL表达式。但提供了很多额外的功能,最出色的就是函数调用简单字符串的模板函数。他需要使用spring提供的解析器来解析,但是他不依赖于spring,可以独立使用。在spring程序当中,我们不用管解析器,由spring来帮我们自动构建。我们只需要写想要表达的字符串,交给spring来进行解析即可。

什么地方会用到SpEL表达式?

使用SpEL表达式的地方应该有很多,据我目前了解的有以下三种情况可以使用:

  • @Value注解可以通过@Value(“${xxxx}”)的形式来获取application当中的配置,使用@Value(“#{xxxx}”)的形式可以使用SpEL表达式
  • spring cache当中@Cache相关的注解当中的key属性值可以使用SpEL表达式
@Override
@Cacheable(value = "rbac:roleSet", key = "T(org.apache.commons.lang3.StringUtils).join(#roles,'|')", unless = "#result == null || #result.size() == 0")
public List<String> getRoleIdsByRole(Set<String> roles) {
	return null;
}
  • xml当中bean标签下property属性注入,是利用属性set方法注入的,然后使用spel表达式也是#{ }
<bean id="numberGuess" class="org.spring.samples.NumberGuess">
    <property name="randomNumber" value="#{ T(java.lang.Math).random() * 100.0 }"/>

    <!-- other properties -->
</bean>
<!--numberGuess.randomNumber相当于是从容器当中获取numberGuess的randomNumber 属性 -->
<bean id="shapeGuess" class="org.spring.samples.ShapeGuess">
    <property name="initialShapeSeed" value="#{ numberGuess.randomNumber }"/>

    <!-- other properties -->
</bean>

二、SpEL解析器

有时候不知道输入的SpEL表达式对不对,可以通过如下方式来进行测试,其中
'Hello World'.concat('!')就是输入的表达式

public static void main(String[] args) {
    // 创建spel表达式分析器
    ExpressionParser parser = new SpelExpressionParser();
    // 输入表达式
    Expression exp = parser.parseExpression("'Hello World'.concat('!')");
    // 获取表达式的输出结果,getValue入参是返回参数的类型
    String value = exp.getValue(String.class);
    System.out.println(value);
}

'Hello World'.concat('!')相当于在Java当中的"Hello World".concat("!") ,Java当中字符串是使用的双引号"字符串",而SpEL表达式使用的是单引号,concat就是String当中的一个拼接方法,SpEL支持调用方法的。输出结果:

SpEL表达式详解

使用new这种表达式也是可以的:

// toUpperCase转换为大写字符
Expression exp = parser.parseExpression("new String('hello world').toUpperCase()");

getValue方法非常重要,他一共有三个参数:

  • Object rootObject:这里我把他当做是元数据对象
  • Class desiredResultType:返回值类型
  • EvaluationContext context:假如有多个对象就不可以使用rootObject,就需要使用EvaluationContext
StandardEvaluationContext context = new StandardEvaluationContext();
 context.setVariable("primes", primes);

三、代码示例

3.1 使用某个对象的属性

public static void main(String[] args) {
    Student student = new Student("张三", 11);
    ExpressionParser parser = new SpelExpressionParser();
    Expression exp = parser.parseExpression("name");
    // 这里就是传入的rootObject参数和返回值类型参数
    String name = exp.getValue(student, String.class);
    System.out.println(name);
}

SpEL表达式详解

根据属性判断是否是某个值

public static void main(String[] args) {
    Student student = new Student("张三", 11);
     ExpressionParser parser = new SpelExpressionParser();
     // 判断student对象当中的name属性是否是张三
     Expression exp = parser.parseExpression("name == '张三'");
     Boolean name = (Boolean) exp.getValue(student);
     System.out.println(name);
 }

SpEL表达式详解

在spring项目当中,我们想要获取某个对象的属性只需要#{容器当中对象的名称.属性名}

3.2 假如元数据对象有多个

@Test
public void test4() {
    Student student = new Student("张三", 11);
    ExpressionParser parser = new SpelExpressionParser();
    Expression exp = parser.parseExpression("#student.name");
    StandardEvaluationContext context = new StandardEvaluationContext();
    // 输入多个数据源
    context.setVariable("student", student);
    context.setVariable("name", "测试");

    String name = exp.getValue(context, String.class);
    // 假如表达式是#name输出结果是 测试
    // 假如表达式是#student.name输出结果是 张三
    System.out.println(name);
}

3.3 systemProperties

在spring项目当中变量systemProperties是预定义的,可以通过#{systemProperties['属性名']}来获取值,systemProperties就是一个系统类,可以获取到jdk版本,系统相关的属性。

public class SystemProperties {
    public static void main(String[] args) {
        Properties properties = System.getProperties();
        Iterator<Map.Entry<Object, Object>> iterator = properties.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Object, Object> entry = iterator.next();
            System.out.println(entry.getKey() + "===" + entry.getValue());
        }
    }
}
@Value("#{systemProperties['user.language']}")
private String name;

systemProperties是内置的系统对象,他就是一个map结构,所谓的内置可以理解为Spring将这个对象提前放入到了StandardEvaluationContext的Variable当中了,我们可直接通过SpEL表达式来获取

四、表达式语言

表达式语言支持以下功能:

  • 文字表达式: 字符串使用单引号'字符串',同时还支持double、int、boolean、Object类型,这些类型都不需要引号。

  • 布尔和关系运算符: 支持的逻辑运算符 and, or, and not

  • 类表达式: T(全类名),java.lang类型不需要是 完全限定,使用方式:T(String)T(java.util.Date),也可以通过这种方式来调用方法。

  • 访问 properties, arrays, lists, maps: 只要用一个.表示嵌套 属性值,属性名称的第一个字母不区分大小写。

    • 数组:inventions[3]
    • List当中存储的对象,获取对象属性:Members[0].Name,属性值是个数组的情况:Members[0].Inventions[6]
    • properties和maps,获取指定key值:Officers['president'],key值假如是个对象,获取对象当中属性的值,Officers['president'].PlaceOfBirth.City,假如是数组Officers['advisors'][0].PlaceOfBirth.Country
  • 方法调用: 'abc'.substring(2, 3)isMember('Mihajlo Pupin'),这两种都是可以的,一种是通过某个对象调用方法,一种是直接调用当前类的方法。

  • 关系运算符: 'black' < 'block'2 < -5.02 == 2,除了标准的关系运算符SpEL支持instanceof和 增则表达式的matches操作。'xyz' instanceof T(int)'5.00' matches '^-?\\d+(\\.\\d{2})?$'。每个符号操作者也可以被指定为一个纯字母变量。这个 避免了在使用的符号有特殊含义的文档类型的问题 其表达被嵌入(例如,XML文档)。文本是等值 比如: lt (<), gt (>), le (<=), ge (>=), eq (==), ne (!=), div (/), mod (%), not (!). 这些都是不区分大小写。

  • 逻辑运算符: 支持的逻辑运算符 and, or, and not,示例:isMember('Nikola Tesla') or isMember('Albert Einstein')

  • 数学运算符: 加法运算符可以用于数字和字符串。减法,乘法 和除法只能在数字被使用。支持其他数学运算符 模量(%)和指数幂(^)。标准的运算符优先级执行。

  • 调用构造函数: 构造函数可以使用new运算符调用。
    new org.spring.samples.spel.inventor.Inventor('Albert Einstein', 'German')

  • Bean引用: 如果解析上下文已经配置,那么bean解析器能够 从表达式使用(@)符号查找bean类。例如:@foo

  • 构造Array: new int[]{1,2,3}@Value("#{new int[]{1,2,3}}")

  • 内嵌lists: {1,2,3,4}代表List,在spring项目当中使用的话就得再嵌套一层,
    @Value("#{{1,2,3,4}}"),list的属性假如也是list可以使用{{'a','b'},{'x','y'}},
    @Value("#{{{'a','b'},{'x','y'}}}") 层次关系一定要屡明白!

  • 内嵌maps: {name:'Nikola',dob:'10-July-1856'}
    {name:{first:'Nikola',last:'Tesla'},dob:{day:10,month:'July',year:1856}}

  • 三元运算符: false ? 'trueExp' : 'falseExp',Elvis操作符使三元运算符语法的缩短,并用于在 Groovy语言。 Java当中的三元:String displayName = name != null ? name : "Unknown";,SpEL当中使用Elvis操作符:null?:'Unknown'@Value("#{systemProperties['pop3.port'] ?: 25}") 如果它不存在,那么将定义为25

  • 变量: 变量可以在使用语法#变量名表达引用。变量使用在StandardEvaluationContext方法的setVariable设置。变量#this 始终定义和指向的是当前的执行对象,变量#root总是 定义和指向root context object。虽然#this可能作为表达式的一些组件被执行 ,但#root总是指 root。

// create an array of integers
List<Integer> primes = new ArrayList<Integer>();
primes.addAll(Arrays.asList(2,3,5,7,11,13,17));

// create parser and set variable primes as the array of integers
ExpressionParser parser = new SpelExpressionParser();
StandardEvaluationContext context = new StandardEvaluationContext();
context.setVariable("primes",primes);

// all prime numbers > 10 from the list (using selection ?{...})
// evaluates to [11, 13, 17]
List<Integer> primesGreaterThanTen = (List<Integer>) parser.parseExpression(
        "#primes.?[#this>10]").getValue(context);

#root我们在使用spring cache的时候经常会用到:

SpEL表达式详解文章来源地址https://www.toymoban.com/news/detail-404184.html

  • bean引用: 如果解析上下文已经配置,那么bean解析器能够 从表达式使用(@)符号查找bean类。
  • 安全导航运算符: 安全导航操作符是用来避免NullPointerException,用法:PlaceOfBirth?.City,代表的是获取PlaceOfBirth对象的City属性。假如PlaceOfBirth为null正常会报空指针,该 安全航行运算符将简单地返回空代替抛出的异常。
  • 用户定义的函数: 支持自定义函数,函数就是方法。
  • 集合投影: 投影允许集合驱动子表达式和解析 生成一个新的集合。
    Members.![placeOfBirth.city] 一个map也可以用于驱动投影。
  • 集合筛选: 选择是一个强大的表达式语言功能,他允许你转换一些 源集合到另一个通过其条目选择。Members.?[Nationality == 'Serbian']map.?[value<27]说白了就是过滤功能
  • 模板表达式: 表达式模板允许文字文本与一个或多个解析块的混合。 你可以每个解析块分隔前缀和后缀的字符, 当然,常见的选择是使用#{}作为分隔符。

到了这里,关于SpEL表达式详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Spring高手之路3——揭秘Spring依赖注入和SpEL表达式

    本篇会给大家举出各种 Spring 属性依赖注入的例子,方便大家理解。 我们在前面的文章中已经使用过 XML 进行 setter 方法的属性注入了,下面让我们再来回顾一下: 我们在前面的文章中也学习过如何在 bean 创建时通过编程方式设置属性: 使用XML进行setter方法注入 首先,我们需

    2024年02月08日
    浏览(45)
  • Spring判断方法名是符合给定的SPEL+表达式的+API

    org.springframework.expression.spel.standard.SpelExpressionParser解析SPEL表达式 org.springframework.expression.spel.support.StandardEvaluationContext 验证方法名是否符合表达式 我们先使用SpelExpressionParser类来解析表达式,然后再创建一个StandardEvaluationContext对象,并将方法名作为变量设置到上下文中。最后

    2024年02月10日
    浏览(41)
  • SPEL表达式注入分析

    在Spring 3中引入了Spring表达式语言(Spring Expression Language,简称SpEL),这是一种功能强大的表达式语言,支持在运行时查询和操作对象图,可以与基于XML和基于注解的Spring配置还有bean定义一起使用。 在Spring系列产品中,SpEL是表达式计算的基础,实现了与Spring生态系统所有产

    2024年04月08日
    浏览(36)
  • 【SpringBoot应用篇】【AOP+注解】SpringBoot+SpEL表达式基于注解实现权限控制

    Spring 表达式语言 SpEL 是一种非常强大的表达式语言,它支持在运行时查询和操作对象图。 它提供了许多高级功能,例如方法调用和基本的字符串模板功能。 表达式语言给静态Java语言增加了动态功能。 Spring 表达式语言最初是为 Spring 社区创建的,它拥有一种受良好支持的表

    2024年02月20日
    浏览(45)
  • Web攻防--Java_SQL注入--XXE注入-- SSTI模板注入--SPEL表达式注入

    编译器在编译sql语句时,会依次进行词法分析、语法分析、语义分析等操作, 预编译技术会让数据库跳过编译阶段,也就无法就进行词法分析,不会被拆开,注入语句也就不会被识别为SQL的,从而防止恶意注入语句改变原有SQL语句本身逻辑。 在使用JDBC进行数据

    2024年02月09日
    浏览(60)
  • spring AOP中pointcut表达式详解

    📢📢📢📣📣📣 哈喽!大家好,我是「奇点」,江湖人称 singularity。刚工作几年,想和大家一同进步🤝🤝 一位上进心十足的【Java ToB端大厂领域博主】!😜😜😜 喜欢java和python,平时比较懒,能用程序解决的坚决不手动解决😜😜😜 ✨ 如果有对【java】感兴趣的【小可

    2024年02月13日
    浏览(41)
  • Day66:WEB攻防-Java安全&SPEL表达式&SSTI模版注入&XXE&JDBC&MyBatis注入

    目录 JavaSec搭建 Hello-Java-Sec搭建 Java安全-SQL注入-JDBCMyBatis JDBC:Java语言连接数据库操作 MyBatis( mybatis是一个优秀的基于java的持久层框架,它内部封装了 jdbc) 代码审计案例:inxedu后台MyBatis注入 Java安全-XXE注入-ReaderBuilder 配置XML允许引入外部解析实体 白盒测试-XXE Java安全-SSTI模版

    2024年04月25日
    浏览(45)
  • 【Spring教程16】Spring框架实战:详解解读AOP配置管理中AOP切入点表达式和通知类型

    欢迎大家回到《 Java教程之Spring30天快速入门》,本教程所有示例均基于Maven实现,如果您对Maven还很陌生,请移步本人的博文《 如何在windows11下安装Maven并配置以及 IDEA配置Maven环境》,本文的上一篇为《 AOP的工作流程和AOP的核心概念》 前面的案例中,有涉及到如下内容: 对于

    2024年02月04日
    浏览(40)
  • Arrays类概述,Lambda表达式

    数组操作工具类,专门用于操作数组元素 2:常用API Lambda概述 Lambda表达式是JDK开始后的一种新语法形式 作用:简化匿名内部类的代码写法 格式: 注意:Lambda表达式只能简化函数式接口的匿名内部类的写法形式。 什么是函数式接口? 首先必须是接口,其次接口中有且仅有一

    2024年02月12日
    浏览(33)
  • Spring:表达式语言

    Spring 表达式(Spring EL) 是一种功能强大的表达式语言,以 #{ 表达式 } 作为定界符,用于在运行时对对象进行访问和操作。通过使用 Spring 表达式达到简化开发、减少逻辑或配置的编写的目的。 Spring EL 主要可以引用 bean ,调用其属性和方法,也可以在 bean 标签中使用 value 属

    2024年02月16日
    浏览(54)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包