流中带有 "Collectors.toList()" 的 SpEL 解析参数不能用作 expressionString?
SpEL parsing parameters with "Collectors.toList()" in stream won't work as expressionString?
这会起作用
parser.parseExpression("#configList.stream().toArray()").getValue(context)
但以下不会
parser.parseExpression("#configList.stream().map(o -> o.ruleId).collect(Collectors.toList())").getValue(context)
F.Y.I上下文构造如下:
Object[] args = joinPoint.getArgs();
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
String[] params = discoverer.getParameterNames(method);
EvaluationContext context = new StandardEvaluationContext();
for (int i = 0; i < params.length; i++) {
context.setVariable(params[i], args[i]);
}
虽然 Java 可以在 SPeL 表达式中使用,但 SPeL 本身是一种独立的语言,并不 完全 支持 Java 语言。来自 documentation:
SpEL is based on a technology agnostic API allowing other expression language implementations to be integrated should the need arise.
要对SPeL表达式中的List进行过滤和映射操作,分别使用collection selection and collection projection:
集合选择示例
// Java:
configList.stream().filter(o -> o.getRuleId() > 2).collect(Collectors.toList())
// SPeL (notice the question mark) :
"#configList.?[ruleId>2]"
集合投影示例
// Java:
configList.stream().map(o -> o.getRuleId()).collect(Collectors.toList())
// SPeL (notice the exclamation mark) :
"#configList.![ruleId]"
我已经建立了一个小例子来演示它:
public class So64738543ExpressionTest {
public static class RuleItem {
private int ruleId;
public RuleItem(int ruleId) {
this.ruleId = ruleId;
}
public int getRuleId() {
return ruleId;
}
}
@Test
public void collectionProjection() {
List<RuleItem> ruleItems = Arrays.asList(new RuleItem(1), new RuleItem(2), new RuleItem(3));
EvaluationContext context = new StandardEvaluationContext(ruleItems);
Expression expression = new SpelExpressionParser().parseExpression("#root.![ruleId]");
Assert.assertEquals(Arrays.asList(1,2,3), expression.getValue(context));
}
}
[编辑]
此外,如果 SPeL 表达式变得越来越复杂,我 强烈建议 将表达式移动到静态方法并使用 T operator
调用它。引用静态方法时不要忘记包含完全限定的包名称。
这会起作用
parser.parseExpression("#configList.stream().toArray()").getValue(context)
但以下不会
parser.parseExpression("#configList.stream().map(o -> o.ruleId).collect(Collectors.toList())").getValue(context)
F.Y.I上下文构造如下:
Object[] args = joinPoint.getArgs();
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
String[] params = discoverer.getParameterNames(method);
EvaluationContext context = new StandardEvaluationContext();
for (int i = 0; i < params.length; i++) {
context.setVariable(params[i], args[i]);
}
虽然 Java 可以在 SPeL 表达式中使用,但 SPeL 本身是一种独立的语言,并不 完全 支持 Java 语言。来自 documentation:
SpEL is based on a technology agnostic API allowing other expression language implementations to be integrated should the need arise.
要对SPeL表达式中的List进行过滤和映射操作,分别使用collection selection and collection projection:
集合选择示例
// Java:
configList.stream().filter(o -> o.getRuleId() > 2).collect(Collectors.toList())
// SPeL (notice the question mark) :
"#configList.?[ruleId>2]"
集合投影示例
// Java:
configList.stream().map(o -> o.getRuleId()).collect(Collectors.toList())
// SPeL (notice the exclamation mark) :
"#configList.![ruleId]"
我已经建立了一个小例子来演示它:
public class So64738543ExpressionTest {
public static class RuleItem {
private int ruleId;
public RuleItem(int ruleId) {
this.ruleId = ruleId;
}
public int getRuleId() {
return ruleId;
}
}
@Test
public void collectionProjection() {
List<RuleItem> ruleItems = Arrays.asList(new RuleItem(1), new RuleItem(2), new RuleItem(3));
EvaluationContext context = new StandardEvaluationContext(ruleItems);
Expression expression = new SpelExpressionParser().parseExpression("#root.![ruleId]");
Assert.assertEquals(Arrays.asList(1,2,3), expression.getValue(context));
}
}
[编辑]
此外,如果 SPeL 表达式变得越来越复杂,我 强烈建议 将表达式移动到静态方法并使用 T operator
调用它。引用静态方法时不要忘记包含完全限定的包名称。