23.2.9 构造List
在SpEl中可以使用“{e1,e2,e3}”的形式来构造一个List,如下示例中我们就构造了一个List。
@Test
public void test09() {
ExpressionParser parser = new SpelExpressionParser();
List<Integer> intList = (List<Integer>)parser.parseExpression("{1,2,3,4,5,6}").getValue();
int index = 0;
for (Integer i : intList) {
Assert.assertTrue(i == ++index);
}
}
如果我们希望构造的List的元素还是一个List,则可以将构造的List的元素定义为“{e1,e2,e3}”这样的形式,如“{{1,2},{3,4,5},{6,7,8,9}}”。
@Test
public void test09_1() {
ExpressionParser parser = new SpelExpressionParser();
List<List<Integer>> list = (List<List<Integer>>)parser.parseExpression("{{1,2},{3,4,5},{6,7,8,9}}").getValue();
int index = 0;
for (List<Integer> intList : list) {
for (Integer i : intList) {
Assert.assertTrue(i == ++index);
}
}
}
如果需要构造一个空的List,则直接将对应的表达式字符串定义为“{}”即可。
23.2.10 构造Map
我们知道Map是可以key-value的形式存在的,在SpEl中如果我们需要构造一个Map则可以使用“{key1:value1,key2:value2}”这样的形式进行定义,即使用大括号包起来,然后key和value之间以冒号“:”分隔构成一个Entry,多个Entry之间以逗号分隔。如下示例中我们就构建了一个key为String,value为Long类型的Map。
@Test
public void test10() {
ExpressionParser parser = new SpelExpressionParser();
Map<String, Long> map = (Map<String, Long>)parser.parseExpression("{'key1':1L,'key2':2L}").getValue();
Assert.assertTrue(map.get("key1").equals(1L));
Assert.assertTrue(map.get("key2").equals(2L));
}
如果需要构造一个空的Map,则只需指定对应的表达式为“{:}”即可。
@Test
public void test10_1() {
ExpressionParser parser = new SpelExpressionParser();
Map<String, Long> map = (Map<String, Long>)parser.parseExpression("{:}").getValue();
Assert.assertTrue(map.isEmpty());
}
23.2.11 构造数组
对于数组的构造就比较简单了,我们可以在表达式中使用Java代码中new的语法来构造一个数组。
@Test
public void test11() {
ExpressionParser parser = new SpelExpressionParser();
int[] nums = (int[])parser.parseExpression("new int[]{1,2,3}").getValue();
Assert.assertTrue(nums.length==3);
}
如果需要构造一个空数组,则可以直接new一个空的数组。多维数组也是支持的,但是多维数组只支持定义一个空的数组,对于需要初始化指定数组元素的定义暂时在SpEl中是不支持的。
@Test
public void test11_1() {
ExpressionParser parser = new SpelExpressionParser();
int[][] nums = (int[][])parser.parseExpression("new int[2][3]").getValue();//正确
int[][] nums2 = (int[][])parser.parseExpression("new int[2][3]{{1,2,3},{4,5,6}}").getValue();//错误
}
23.2.12 集合选择
SpEl允许我们将集合中的某些元素选出组成一个新的集合进行返回,这就是所谓的集合。打个比方,我们有一个List,其包含1-9共9个数字,通过集合选择的功能我们可以选出其中的奇数组成一个新的List进行返回,即1、3、5、7、9。集合的选择使用的语法是“collection.?[condition]”,condition中直接使用的属性、方法等都是针对于集合中的元素来的。如下示例中我们的user对象的getInterests()方法返回包含三个元素的List,然后我们通过endsWith(‘Ball’)筛选出以Ball结尾的元素组成一个新的List。
@Test
public void test12_1() {
Object user = new Object() {
public List<String> getInterests() {
List<String> interests = new ArrayList<String>();
interests.add("BasketBall");
interests.add("FootBall");
interests.add("Movie");
return interests;
}
};
ExpressionParser parser = new SpelExpressionParser();
List<String> interests = (List<String>)parser.parseExpression("interests.?[endsWith('Ball')]").getValue(user);
Assert.assertTrue(interests.size() == 2);
Assert.assertTrue(interests.get(0).equals("BasketBall"));
Assert.assertTrue(interests.get(1).equals("FootBall"));
}
对于Map的选择而言,其中的condition中直接使用的属性和方法针对的主体都是Map的Entry。如下示例中我们通过条件value.endsWith(‘Ball’)选出Map中value以Ball结尾的Entry组成一个新的Map进行返回,对应的条件相当于Entry.getValue().endsWith(“Ball”)。
@Test
public void test12_2() {
Object user = new Object() {
public Map<String, String> getInterests() {
Map<String, String> interests = new HashMap<String, String>();
interests.put("key1", "BasketBall");
interests.put("key2", "FootBall");
interests.put("key3", "Movie");
return interests;
}
};
ExpressionParser parser = new SpelExpressionParser();
Map<String, String> interests = (Map<String, String>)parser.parseExpression("interests.?[value.endsWith('Ball')]").getValue(user);
Assert.assertTrue(interests.size() == 2);
Assert.assertTrue(interests.get("key1").equals("BasketBall"));
Assert.assertTrue(interests.get("key2").equals("FootBall"));
}
23.2.13 集合投影
集合投影的意思是将集合中每个元素的某部分内容的组成一个新的集合进行返回。集合投影的语法是“collection.![projectionExpression]”,其中projectionExpression中直接使用的属性和方法都是针对于collection中的每个元素而言的,对于List而言其就表示List中的每个元素,对于Map而言,其就表示Map中的每个Entry。在如下示例中我们就将List中的每一个元素调用endsWith()方法后的结果组成一个新的List进行返回。
@Test
public void test13_1() {
Object user = new Object() {
public List<String> getInterests() {
List<String> interests = new ArrayList<String>();
interests.add("BasketBall");
interests.add("FootBall");
interests.add("Movie");
return interests;
}
};
ExpressionParser parser = new SpelExpressionParser();
List<Boolean> interests = (List<Boolean>)parser.parseExpression("interests.![endsWith('Ball')]").getValue(user);
Assert.assertTrue(interests.size() == 3);
Assert.assertTrue(interests.get(0).equals(true));
Assert.assertTrue(interests.get(1).equals(true));
Assert.assertTrue(interests.get(2).equals(false));
}
Map进行投影的结果是一个List。如下示例中我们就将一个Map的value投影为一个List,对应List中元素的顺序是不定的。
@Test
public void test13_2() {
Object user = new Object() {
public Map<String, String> getInterests() {
Map<String, String> interests = new HashMap<String, String>();
interests.put("key1", "BasketBall");
interests.put("key2", "FootBall");
interests.put("key3", "Movie");
return interests;
}
};
ExpressionParser parser = new SpelExpressionParser();
List<String> interests = (List<String>)parser.parseExpression("interests.![value]").getValue(user);
Assert.assertTrue(interests.size() == 3);
for (String interest : interests) {
Assert.assertTrue(interest.equals("BasketBall") || interest.equals("FootBall") || interest.equals("Movie"));
}
}
23.2.14 设置变量
在前面我们已经介绍了EvaluationContext和rootObject的用法,貌似使用EvaluationContext时直接使用rootObject更简单一些。那是不是所有使用EvaluationContext的地方都可以改成使用rootObject呢?答案是否定的。EvaluationContext的功能相比rootObject而言还是要丰富很多的,如其可以设置变量、方法等供表达式使用。对于变量而言,我们可以通过EvaluationContext的setVariable()方法进行设置,然后在表达式中使用时通过“#varName”的形式进行使用。如下示例中我们就给EvaluationContext设置了一个名为“user”的变量,然后在表达式中通过“#user”来使用该变量。
@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对象。在如下示例中#root就指向了对应的user对象。
@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永远指向当前对象,其通常用于集合类型,表示集合中的一个元素。如下示例中我们就使用了#this表示当前元素以选出奇数作为一个新的List进行返回。
@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);
}
}
23.2.15 注册方法
StandardEvaluationContext允许我们在其中注册方法,然后在表达式中使用对应的方法。注册的方法必须是一个static类型的公有方法。注册方法是通过StandardEvaluationContext的registerFunction(funName,method)方法进行,其中第一个参数表示需要在表达式中使用的方法名称,第二个参数表示需要注册的java.lang.reflect.Method。在表达式中我们可以使用类似于“#funName(params…)”的形式来使用对应的方法。如下示例中我们就通过StandardEvaluationContext注册了一个名叫plusTen的方法。
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);
}
相关推荐
漏洞的根源在于Spring Cloud Gateway Actuator API 对用户输入的参数没有进行充分的验证和过滤,这使得攻击者可以通过构造恶意的SpEL表达式来执行任意系统命令。例如,当Actuator的某个端点接受到包含SpEL表达式的...
二、Spring Boot 控制器配置 在 Controller 中,我们需要使用 Model 来传递参数。例如: ```java @RequestMapping("/index") public String index(Model model) { model.addAttribute("loginName", "admin"); ...
4. **基于表达式的SpEL(Spring Expression Language)**:提供了强大的表达式语言,用于在运行时查询和操作对象图。 5. **RESTful Web服务支持**:Spring MVC模块增加了对RESTful服务的支持,通过`@RequestMapping...
1.15 【第五章】Spring表达式语言 之 5.1 概述 5.2 SpEL基础 ——跟我学spring3 . . . . . . . . . . . . . . .177 1.16 【第五章】Spring表达式语言 之 5.3 SpEL语法 ——跟我学spring3 . . . . . . . . . . . . ....
同时,Spring3.0引入了一种新的表达式语言——Spring 表达式语言(SpEL),它允许在XML和注解中定义基于bean的定义。此外,Spring3.0还支持REST Web服务和注解的格式化,例如,可以使用@DateTimeFormat和@...
`@PreAuthorize`允许使用SpEL(Spring Expression Language)表达式进行更复杂的权限检查。 5. **自定义访问决策策略** 默认的访问决策管理器可能不满足所有需求,我们可以创建自定义的访问决策策略。例如,可以...
这里的`#{systemProperties['java.version']}`就是一个SpEL表达式,它会获取系统属性`java.version`的值。 除了`@Value`,Spring还提供了其他许多工具和注解,如`@Autowired`用于自动装配Bean,`@Component`、`@...
12. **Spring Expression Language (SpEL)**:SpEL是Spring的表达式语言,用于在运行时查询和操作对象图。 13. **事件驱动架构**:Spring支持事件驱动编程模型,允许组件之间通过发布和监听事件进行通信。 14. **...
2.5.6引入了Spring Expression Language (SpEL),这是一个强大的表达式语言,用于在运行时查询和操作对象图。此外,它还引入了基于注解的配置,使得开发者可以使用注解替代XML配置文件,大大简化了项目设置。这个...
- `spring-expression.jar`(可能需要):Spring表达式语言(SpEL),用于在运行时查询和操作对象图。 在使用这些jar包时,你需要确保它们都在你的项目类路径(ClassPath)下。如果你使用Maven或Gradle等构建工具,...
同时,Spring 4.1还引入了Spring Expression Language (SpEL)的增强,允许更灵活的表达式计算。 2. **Spring 4.3.x系列**:这个版本系列是对4.1的重大升级,4.3.15和4.3.24是其中的稳定版本。Spring 4.3引入了更多...
8. **Spring表达式语言(SpEL)**:Spring Expression Language是Spring框架内的一种强大表达式语言,用于在运行时查询和操纵对象图。它可以用于Bean装配、AOP等方面,提供灵活的数据绑定和表达式计算。 9. **...
Spring 3.1新增了Spring表达式语言(SpEL),这是一种强大的领域特定语言,用于在运行时查询和操纵对象图。SpEL支持丰富的操作符和函数,可以用于属性访问、算术运算、条件判断等多种场景。SpEL不仅可以作为字符串在...
Spring 3.0 中引入了一个新的表达式语言——**Spring Expression Language (SpEL)**。这是一种强大的脚本语言,用于在Spring组件之间描述任务和配置。SpEL可以更好地与XML配置文件交互,并且对于安全性和集成方面...
【第五章】Spring表达式语言(SpEL)是一个强大的表达式语言,支持在运行时查询和操作对象图。5.1节概述SpEL,5.2节和5.3节详细说明SpEL的基础和语法,5.4节则展示了如何在Bean定义中使用SpEL。 【第六章】面向切面...
5. **更强大的SpEL(Spring Expression Language)**:Spring的表达式语言在4.2版本中也有所增强,提供了更多函数和操作符,使得在运行时动态评估表达式更为强大。 综上所述,`spring4.2.jar`是Spring框架4.2版本的...
7. **Spring表达式语言(SpEL)**:Spring Expression Language是Spring 2.0引入的一种强大表达式语言,用于在运行时查询和操作对象图。SpEL可以用在配置中,用于动态计算属性值。 8. **单元测试与集成测试**:...
5. **Spring Expression Language (SpEL)**:一种强大的表达式语言,用于在运行时查询和操作对象图。 四、实践应用 在实际项目中,开发者可以利用Spring框架4.3.9.RELEASE来构建模块化的应用,通过DI管理组件之间的...
8. **Spring Expression Language (SpEL)**:spring-expression-4.1.5.RELEASE.jar提供了强大的表达式语言,用于在运行时查询和操作对象图。它广泛应用于配置文件中的条件判断、属性设置等场景。 9. **Spring ...