SpEL(1)

概述

Spring表达式语言(Spring Expression Language)缩写为“SpEL”,能在运行时构建复杂表达式、存取对象图属性、对象方法调用等等,并且能与Spring功能整合

SpEL是单独模块只依赖core模块,可单独使用

作用

  1. 基本表达式
    字面量表达式、关系,逻辑与算数运算表达式、字符串连接、截取表达式、三目运算、Elibis表达式、正则表达式、括号优先级表达式;
  2. 类相关表达式
    类类型表达式、类实例化、instanceof表达式、变量定义引用、赋值表达式、自定义函数、对象属性存取、安全导航表达式、对象方法调用、bean引用;
  3. 集合相关表达式
    内联List、内联数组、集合、字典访问、列表字典数组修改、集合投影、集合选择’
  4. 其他表达式
    模板表达式

注意:SpEL表达式中的关键字是不区分大小写的

Hello World

第一种
SpELHelloTest.java

package com.test;

import org.junit.Assert;
import org.junit.Test;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

public class SpELHelloTest {
    @Test
public void SpELHelloTest(){
    ExpressionParser parser=new SpelExpressionParser();
    Expression expression=parser.parseExpression("('Hello'+' World').concat(#end)");
    EvaluationContext context =new StandardEvaluationContext();
    context.setVariable("end", "!");
    Assert.assertTrue("Hello World!".equals(expression.getValue(context)));
}
}

步骤
1. 构造解析器
SpEL使用ExpressionParser接口表示解析器,提供了SpelExpressionParser实现
2. 解析器解析字符串表达式
使用ExpressionParser的parseExpression来解析相应的表达式为Expression对象
3. 构造上下文
准备变量定义等表达式需要的上下文数据
4. 根据上下文得到表达式运算后的值
通过Expression接口的getValue方法根据上下文获取表达式值

第二种
SpELHelloTest .java

package com.test;

import org.junit.Assert;
import org.junit.Test;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

public class SpELHelloTest {
    @Test
public void SpELHelloTest(){
    ExpressionParser parser=new SpelExpressionParser();
    //ParserContext 接口用于定义字符串是不是表达式以及模板的开始和结束字符
    ParserContext parserContext=new ParserContext() {
        //是否是模板
        @Override
        public boolean isTemplate() {
            return true;
        }
        //结束字符
        @Override
        public String getExpressionSuffix() {
            return "}";
        }
        //开始字符
        @Override
        public String getExpressionPrefix() {
            return "#{";
        }
    };
    String template="#{'Hello '}#{'World!'}";
    //Expression expression=parser.parseExpression("('Hello'+' World').concat(#end)");
    Expression expression=parser.parseExpression(template, parserContext);
    //EvaluationContext context =new StandardEvaluationContext();
    //context.setVariable("end", "!");
    Assert.assertTrue("Hello World!".equals(expression.getValue()));
}
}

SpEL原理及接口

  1. 表达式:“做什么”
  2. 解析器:“谁来做”,将字符串表达式解析为表达式对象
  3. 上下文:“在哪做”,表达式对象的执行环境,该环境可能定义了变量、自定义函数、类型转换等

ExpressionParser.class

 public abstract interface ExpressionParser
{
  public abstract Expression parseExpression(String paramString)
    throws ParseException;

  public abstract Expression parseExpression(String paramString, ParserContext paramParserContext)
    throws ParseException;
}
  • ExpressionParser接口表示解析器,SpelExpressionParser为实现,其中ParserContext 接口用于定义字符串是不是表达式以及模板的开始和结束字符;
  • EvaluationContext接口表示上下文环境,StandardEvaluationContext为实现,setRootObject设置跟对象,setVariable设置自定义变量,registerFunction注册自定义函数;
  • Expression 接口表示表达式对象,getVlaue()取得表达式的值,setValue()设置表达式的值;
### SpEL 使用指南 Spring Expression Language (SpEL) 是 Spring 框架中用于操作和访问对象图的一种强大表达式语言。它支持运行时查询和操作对象图,具有高度的灵活性和可扩展性。SpEL 可以在多种场景中使用,例如配置、条件判断、缓存控制等。 #### 1. 基本语法 SpEL表达式通常以 `#{...}` 的形式出现,可以在 Spring 的 XML 配置文件或注解中使用。例如: ```java @Value("#{systemProperties['user.name']}") private String userName; ``` 该表达式从系统属性中获 `user.name` 的值,并将其注入到 `userName` 字段中[^1]。 #### 2. 字面量 SpEL 支持多种字面量类型,包括字符串、数字、布尔值等。例如: ```java @Value("#{'Hello, World!'}") private String greeting; ``` 该表达式将字符串 `"Hello, World!"` 注入到 `greeting` 字段中[^1]。 #### 3. 运算符 SpEL 支持常见的算术运算符、比较运算符和逻辑运算符。例如: ```java @Value("#{2 + 3 * 4}") private int result; ``` 该表达式计算 `2 + 3 * 4` 的结果,并将其注入到 `result` 字段中。 #### 4. 方法调用 SpEL 允许调用对象的方法。例如: ```java @Value("#{T(java.util.Arrays).asList('a', 'b', 'c')}") private List<String> list; ``` 该表达式调用 `Arrays.asList` 方法,创建一个包含 `'a'`、`'b'` 和 `'c'` 的列表,并将其注入到 `list` 字段中。 #### 5. 属性访问 SpEL 支持通过点号运算符访问对象的属性。例如: ```java @Value("#{someBean.someProperty}") private String someProperty; ``` 该表达式从 `someBean` 对象中获 `someProperty` 属性的值,并将其注入到 `someProperty` 字段中。 #### 6. 条件表达式 SpEL 支持三元运算符,用于条件判断。例如: ```java @Value("#{someBean.someValue > 10 ? 'Greater than 10' : 'Less than or equal to 10'}") private String conditionResult; ``` 该表达式根据 `someBean.someValue` 的值进行条件判断,并将结果注入到 `conditionResult` 字段中[^1]。 #### 7. 集合操作 SpEL 支持对集合进行操作,例如过滤和投影。例如: ```java @Value("#{someBean.listOfNumbers.?[#this > 5]}") private List<Integer> filteredList; ``` 该表达式从 `someBean.listOfNumbers` 中筛选出大于 5 的元素,并将其注入到 `filteredList` 字段中。 #### 8. 异常处理 SpEL 支持通过 `?:` 运算符处理异常。例如: ```java @Value("#{someBean.someMethod() ?: 'Default Value'}") private String valueWithDefault; ``` 如果 `someBean.someMethod()` 抛出异常,则注入 `'Default Value'` 到 `valueWithDefault` 字段中。 --- ### 常见问题及解决方案 #### 1. 表达式无法解析 **问题描述:** 在使用 SpEL 表达式时,可能会遇到 `ExpressionParseException` 异常,表示表达式无法解析。 **解决方案:** 检查表达式的语法是否正确,确保所有操作符和方法调用都符合 SpEL 的规范。 #### 2. 方法调用失败 **问题描述:** 在调用对象的方法时,可能会遇到 `MethodInvocationException` 异常。 **解决方案:** 确保调用的方法存在且具有正确的参数类型。如果方法需要参数,确保在表达式中提供正确的参数值。 #### 3. 集合操作性能问题 **问题描述:** 在对大型集合进行操作时,可能会遇到性能问题。 **解决方案:** 考虑在数据源端进行过滤或分页,避免在 SpEL 表达式中处理大量数据。 #### 4. 条件表达式逻辑错误 **问题描述:** 在使用条件表达式时,可能会出现逻辑错误,导致预期外的结果。 **解决方案:** 仔细检查条件表达式的逻辑,确保条件判断的顺序和逻辑正确。 --- ### 示例代码 以下是一个完整的示例,展示如何在 Spring 中使用 SpEL 表达式: ```java import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component public class SpELExample { @Value("#{systemProperties['user.name']}") private String userName; @Value("#{2 + 3 * 4}") private int result; @Value("#{T(java.util.Arrays).asList('a', 'b', 'c')}") private List<String> list; @Value("#{someBean.someProperty}") private String someProperty; @Value("#{someBean.someValue > 10 ? 'Greater than 10' : 'Less than or equal to 10'}") private String conditionResult; @Value("#{someBean.listOfNumbers.?[#this > 5]}") private List<Integer> filteredList; @Value("#{someBean.someMethod() ?: 'Default Value'}") private String valueWithDefault; // Getters and setters } ``` --- ### 调试技巧 1. **日志输出:** 在调试 SpEL 表达式时,可以通过日志输出表达式的结果,帮助定位问题。 2. **单元测试:** 编写单元测试来验证 SpEL 表达式的行为,确保其按预期工作。 3. **表达式评估:** 使用 Spring 的 `ExpressionParser` 手动评估表达式,检查其输出是否符合预期。 --- ### 总结 SpEL 是 Spring 框架中一个非常强大的工具,能够简化配置和逻辑处理。通过合理使用 SpEL,可以提高代码的灵活性和可维护性。然而,需要注意表达式的复杂性和性能影响,确保在实际应用中平衡功能和效率。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值