首页 > 其他分享 >Spring表达式语言(SPEL)学习(03)

Spring表达式语言(SPEL)学习(03)

时间:2024-01-13 16:00:43浏览次数:23  
标签:03 parseExpression Spring parser SPEL context new expression public

rootObject

在表达式中直接写name和getName(),这时候Expression是无法解析的,因为其不知道name和getName()对应什么意思

@Test
public void test06() {
	 ExpressionParser parser = new SpelExpressionParser();
	 parser.parseExpression("name").getValue();
	 parser.parseExpression("getName()").getValue();
}

当表达式是基于某一个对象时,我们可以把对应的对象作为一个rootObject传递给对应的Experssion进行取值

@Test
public void test07() {
    Object user = new Object() {
        public String getName() {
        	return "abc";
        }
    };
    ExpressionParser parser = new SpelExpressionParser();
    Assert.assertTrue(parser.parseExpression("name").getValue(user, String.class).equals("abc"));
    Assert.assertTrue(parser.parseExpression("getName()").getValue(user, String.class).equals("abc"));
}

设置上下文

通过指定EvaluationContext我们可以让name和getName()变得有意义,指定了EvaluationContext之后,Expression将根据对应的EvaluationContext来进行解析

@Test
public void test06() {
    Object user = new Object() {
    public String getName() {
        	return "abc";
        }
    };
    EvaluationContext context = new StandardEvaluationContext(user);
    ExpressionParser parser = new SpelExpressionParser();
    Assert.assertTrue(parser.parseExpression("name").getValue(context, String.class).equals("abc"));
    Assert.assertTrue(parser.parseExpression("getName()").getValue(context, String.class).equals("abc"));
}

设置变量

@Test
public void test14() {
    Object user = new Object() {
        public String getName() {
        	return "abc";
        }
    };
    EvaluationContext context = new StandardEvaluationContext();
    //1、设置变量
    context.setVariable("user", user);
    ExpressionParser parser = new SpelExpressionParser();
    //2、表达式中以#varName的形式使用变量
    Expression expression = parser.parseExpression("#user.name");
    //3、在获取表达式对应的值时传入包含对应变量定义的EvaluationContext
    String userName = expression.getValue(context, String.class);
    //表达式中使用变量,并在获取值时传递包含对应变量定义的EvaluationContext。
    Assert.assertTrue(userName.equals("abc"));
}

#root

root在表达式中永远都指向对应EvaluationContext的rootObject对象

@Test
public void test14_1() {
    Object user = new Object() {
        public String getName() {
        	return "abc";
        }
    };
    EvaluationContext context = new StandardEvaluationContext(user);
    ExpressionParser parser = new SpelExpressionParser();
 	Assert.assertTrue(parser.parseExpression("#root.name").getValue(context).equals("abc"));
}

#this

this永远指向当前对象,其通常用于集合类型,表示集合中的一个元素

@Test
public void test14_2() {
    ExpressionParser parser = new SpelExpressionParser();
    List<Integer> intList = (List<Integer>)parser.parseExpression("{1,2,3,4,5,6}").getValue();
    EvaluationContext context = new StandardEvaluationContext(intList);
    //从List中选出为奇数的元素作为一个List进行返回,1、3、5。
    List<Integer> oddList = (List<Integer>)parser.parseExpression("#root.?[#this%2==1]").getValue(context);
    for (Integer odd : oddList) {
    	Assert.assertTrue(odd%2 == 1);
    }
}

注册方法

StandardEvaluationContext允许我们在其中注册方法,然后在表达式中使用对应的方法,注册的方法必须是一个static类型的公有方法。注册方法是通过StandardEvaluationContext的registerFunction(funName,method)方法进行。参数1表示需要在表达式中使用的方法名称,参数2表示需要注册的java.lang.reflect.Method。在表达式中可以使用类似与#funName(params...)的形式来使用对应的方法

static class MathUtils {
    public static int plusTen(int i) {
    	return i+10;
    }
}
 
@Test
public void test15() throws NoSuchMethodException, SecurityException {
    ExpressionParser parser = new SpelExpressionParser();
    //1、获取需要设置的java.lang.reflect.Method,需是static类型
    Method plusTen = MathUtils.class.getDeclaredMethod("plusTen", int.class);
    StandardEvaluationContext context = new StandardEvaluationContext();
    //2、注册方法到StandardEvaluationContext,第一个参数对应表达式中需要使用的方法名
    context.registerFunction("plusTen", plusTen);
    //3、表达式中使用注册的方法
    Expression expression = parser.parseExpression("#plusTen(10)");
    //4、传递包含对应方法注册的StandardEvaluationContext给Expression以获取对应的值
    int result = expression.getValue(context, int.class);
    Assert.assertTrue(result == 20);
}

赋值

SPEL支持给表达式赋值,其是通过Expression的setValue()方法进行的,在赋值时需要指定rootObject或对应的EvaluationContext

@Test
public void test() {
    ExpressionParser parser = new SpelExpressionParser();
    Date d = new Date();
    
    Expression expression = parser.parseExpression("date");
    //设日期为1号 此处为date,其原理是通过调用Date类的setDate方法,必须指定是set开头的方法
    expression.setValue(d, 1);
    Object value = expression.getValue(d);
    System.out.println(value);

    //其原理是通过调用Date类的setYear方法
    expression = parser.parseExpression("year");
    expression.setValue(d, 2023);
    value = expression.getValue(d);
    System.out.println(value);
}

对于List而言,在进行赋值时是通过元素的索引进行的,且对应的索引是必须存在的

@Test
public void test09() {
    ExpressionParser parser = new SpelExpressionParser();
    List<Integer> list = new ArrayList<Integer>(1);
    list.add(0);//添加一个元素0
    EvaluationContext context = new StandardEvaluationContext();
    //添加变量以方便表达式访问
    context.setVariable("list", list);
    //设置第一个元素的值为1
    Expression expression = parser.parseExpression("#list[0]");
    expression.setValue(context, 1);
    int first = (Integer) expression.getValue(context);
    System.out.println(first);
}

对于Map的赋值是通过key进行的,对应的key在Map中可以先不存在

@Test
public void test10() {
    ExpressionParser parser = new SpelExpressionParser();
    Map<String, Integer> map = new HashMap<>();
    EvaluationContext context = new StandardEvaluationContext();
    //添加变量以方便表达式访问
    context.setVariable("map", map);
    //设置第一个元素的值为1
    Expression expression = parser.parseExpression("#map['key1']");
    expression.setValue(context, 1);
    int first = (Integer) expression.getValue(context);
    System.out.println(first);
}

标签:03,parseExpression,Spring,parser,SPEL,context,new,expression,public
From: https://www.cnblogs.com/penggx/p/17962448

相关文章

  • 2024-01-03:用go语言,给你两个长度为 n 下标从 0 开始的整数数组 cost 和 time, 分别表示
    2024-01-03:用go语言,给你两个长度为n下标从0开始的整数数组cost和time,分别表示给n堵不同的墙刷油漆需要的开销和时间。你有两名油漆匠,一位需要付费的油漆匠,刷第i堵墙需要花费time[i]单位的时间,开销为cost[i]单位的钱。一位免费的油漆匠,刷任意一堵墙的时间为1......
  • 【五期李伟平】CCF-A(AAAI'21)Game of Gradients: Mitigating Irrelevant Clients in Fe
    Nagalapatti,Lokesh,andR.Narayanam."GameofGradients:MitigatingIrrelevantClientsinFederatedLearning."(2021).  针对联邦学习中相关客户端选择(FRCS)的问题,本文提出一种可以选择具有相关数据的客户端的方法,并提出一个检测拥有特定目标标签数据的客户端......
  • Spring事务状态处理
    Spring事务提交后执行:深入理解和实践在Java开发中,Spring框架的事务管理是一个核心概念,尤其是在企业级应用中。理解和正确使用Spring事务对于保证应用的数据一致性和稳定性至关重要。本文将深入探讨在Spring中事务提交后的执行逻辑,这是一个经常被忽视但又极为重要的部分。事务的......
  • Spring踩坑
    测试默认测java对应层级下的东西如果test和java层级不在对应位置可以手动写Test的路径来更改@Component=@Repository@Service@Controller对于WebMvcConfigurer加不加EnableWebMvc都可以对于WebMvcConfigurationSupport不能加EnableWebMvc总结:以后都不加EnableWe......
  • 手拉手Springboot获取yml配置文件信息
    环境介绍技术栈springboot3软件版本mysql8IDEAIntelliJIDEA2022.2.1JDK17SpringBoot3.1.7配置文件说明:启动配置文件优先级:properties高于yml配置文件application.ymlyml是JSON的超集,简洁而强大,是一种专门用来书写配置文件的语言,可以替代application.properties。在创建一个S......
  • 如何让spring扫描到自定义注解的组件
    ClassPathScanningCandidateComponentProviderscanner=newClassPathScanningCandidateComponentProvider(true);scanner.addIncludeFilter(newAnnotationTypeFilter(Tenant.class));Set<BeanDefinition>beanDefinitions=scanner.findCandidat......
  • 基于SpringBoot+Vue的居家养老系统设计实现(源码+lw+部署文档+讲解等)
    (文章目录)前言:heartpulse:博主介绍:✌全网粉丝10W+,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌:heartpulse:......
  • 用这4招 优雅的实现Spring Boot 异步线程间数据传递
    你好,我是蜗牛!在实际开发中需要在父子线程之间传递一些数据,比如用户登录信息使用ThreadLocal存放保证线程隔离,代码如下:/***@author公众号:woniuxgg*@description用户上下文信息*/publicclassUserUtils{privatestaticfinalThreadLocal<String>userLocal=new......
  • Springcloud智慧工地管理云平台源码 AI智能识别
    智慧工地解决方案一、现状描述 建筑工程建设具有明显的生产规模大宗性与生产场所固定性的特点。建筑企业70%左右的工作都发生在施工现场,施工阶段的现场管理对工程成本、进度、质量及安全等至关重要。同时随着工程建设规模不断扩大,工艺流程纷繁复杂,如何搞好现场施工现场管理,控制......
  • Python中出现"No module named 'requests'"的图文解决办法
    第一步找到pycharm中的虚拟环境的位置第二步打开虚拟环境位置的文件夹 找到Scripts的这个文件夹然后复制该文件夹的地址第三步打开“运行”(可以用快捷键WIN+R键打开)然后输入cmd第四步切换目录到虚拟环境的盘符输入“D:”(我的虚拟环境在D盘所以切换到D盘)第五......