Java Spring表达式语言使用映射作为上下文

Java Spring表达式语言使用映射作为上下文,java,spring,Java,Spring,我正在使用spring表达式语言来解析一些表达式。我遇到了这样一个场景,运行表达式所针对的上下文是一个映射或由BeanUtils创建的动态bean Map<String, Object> props= new HashMap<>(); props.put("name", "john"); ExpressionParser parser = new SpelExpressionParser(); EvaluationContext context = new Standar

我正在使用spring表达式语言来解析一些表达式。我遇到了这样一个场景,运行表达式所针对的上下文是一个映射或由BeanUtils创建的动态bean

Map<String, Object> props= new HashMap<>();
props.put("name", "john");
ExpressionParser parser = new SpelExpressionParser();
EvaluationContext context = new StandardEvaluationContext();
Expression exp = parser.parseExpression("name==john");
boolean s  = exp.getValue(context, Boolean.class);
Map props=newhashmap();
道具。放置(“姓名”、“约翰”);
ExpressionParser=new SpelExpressionParser();
EvaluationContext=新标准EvaluationContext();
表达式exp=parser.parseExpression(“name==john”);
布尔s=exp.getValue(上下文,boolean.class);

这是因为名称不是上下文中定义的公共属性。任何关于如何使用spring表达式语言实现此类功能的想法

@John Kiragu您都可以通过创建一个与映射一起工作的自定义属性访问器来实现。然后使用SimpleEvaluationContext。见下例:

  PropertyAccessor accessor = new MyCustomPropertyAccessor();
  SimpleEvaluationContext evaluationContext = new SimpleEvaluationContext.Builder(accessor).
                        withRootObject(contextObject).build();
enter code here
然后,自定义属性访问器将覆盖读取方法:

public class MyCustomPropertyAccessor implements PropertyAccessor {

    @Override
    public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException {
      // your custom code

    }
    @Override
    public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException {
    // your custom code

    }
}

另外,如果地图不适用于您,请尝试使用
DynaClass

代码中有两个错误。首先,需要在表达式中的文本字符串
'john'
周围使用单引号。其次,需要将变量
props
作为上下文的根对象传递。解决这些问题后,您需要使用
MapAcessor
作为属性访问器直接访问地图属性:

    Map<String, Object> props = new HashMap<>();
    props.put("name", "john");
    ExpressionParser parser = new SpelExpressionParser();
    StandardEvaluationContext context = new StandardEvaluationContext(props);
    context.addPropertyAccessor(new MapAccessor());
    Expression exp = parser.parseExpression("name=='john'");
    boolean s  = exp.getValue(context, Boolean.class);
Map props=newhashmap();
道具。放置(“姓名”、“约翰”);
ExpressionParser=new SpelExpressionParser();
StandardEvaluationContext=新的StandardEvaluationContext(道具);
addPropertyAccessor(新的MapAccessor());
表达式exp=parser.parseExpression(“name=='john'”);
布尔s=exp.getValue(上下文,boolean.class);

正如@Marco所说,需要做一些修改

  • 在表达式中的文字字符串
    'john'
    周围使用单引号
  • 您需要将变量props作为上下文的根对象传递
  • 但是我们可以使用文档中提到的方法直接访问地图

    // Officer's Dictionary
    
    Inventor pupin = parser.parseExpression("Officers['president']").getValue(
            societyContext, Inventor.class);
    
  • 使用
    #这个['name']

  • 变量#始终定义并引用当前 评估对象(针对其解析非限定引用)

    修改后,代码将如下所示:

        Map<String, Object> props= new HashMap<>();
        props.put("name", "john");
        ExpressionParser parser = new SpelExpressionParser();
        EvaluationContext context = new StandardEvaluationContext(props);
        Expression exp = parser.parseExpression("#this['name']=='john'");
        boolean s  = exp.getValue(props, Boolean.class);
    
    Map props=newhashmap();
    道具。放置(“姓名”、“约翰”);
    ExpressionParser=new SpelExpressionParser();
    EvaluationContext=新标准EvaluationContext(道具);
    表达式exp=parser.parseExpression(#this['name']=='john');
    布尔s=exp.getValue(props,boolean.class);