当前位置: 首页 > 知识库问答 >
问题:

不能使用Map调用SPeL Expression.setvalue()

孙承
2023-03-14

我正在编写一些代码,以允许使用Spring表达式语言进行动态属性更改。我传入一个bean名称、属性名称和新值的表达式,所有字符串。

这对于类型string、int、boolean和list的属性非常有效。我无法让地图属性工作。我已经看了SPeL留档,包括示例,但我没有看到我所做的任何错误。我得到的例外是没有帮助的。

忽略try/ak块,基本代码如下:

ExpressionParser parser = new SpelExpressionParser();
Expression parsedPropertyNameExpression = parser.parseExpression(propertyName);
SimpleEvaluationContext evalContext = SimpleEvaluationContext.forReadWriteDataBinding().build();
Object currentValue = parsedPropertyNameExpression.getValue(evalContext, bean);
parsedPropertyNameExpression.setValue(evalContext, bean, expression);

当我的“表达式”是“789,0123,345”并且我正在设置的属性是一个列表时,这工作得非常好。

但是,当我设置一个属性类型Map (""), 其中表达式值为{abc:'def', ghi:'jkl'}时,会得到以下异常:

 org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [java.util.Map<java.lang.String, java.lang.String>]

我尝试了该表达式字符串的不同变体,结果基本相同。

更新:

我注意到下面的SO帖子:如何使用@Value Spring注释注入Map?。

其中一个不被接受的答案提到在属性中定义一个映射,并将其注入@Value注释,我认为这使用了类似的机制。我如何在代码中做到这一点?

共有1个答案

訾高飞
2023-03-14

我得到的例外是没有帮助的。

没有找到能够从类型[java.lang.字符串]转换为类型[java.util.映射]的转换器

对我来说似乎很清楚。

没有内置支持将贴图的字符串表示形式转换为map对象。

您可以注册自定义函数,或者在SpEL表达式中使用JacksonObjectMapperbean引用。

编辑

这里有一种方法可以做到这一点(使用杰克逊的自定义转换器)...

public class So55485198Application {

    public static void main(String[] args) {
        Bean bean = new Bean();
        getAndSet("list", bean, "abc, def");
        getAndSet("map", bean, "{'abc':'def'}");
    }

    public static void getAndSet(String propertyName, Bean bean, String expression) {
        ExpressionParser parser = new SpelExpressionParser();
        Expression parsedPropertyNameExpression = parser.parseExpression(propertyName);
        DefaultConversionService conversionService = new DefaultConversionService();
        conversionService.addConverter(new StringToMapConverter());
        SimpleEvaluationContext evalContext = SimpleEvaluationContext.forReadWriteDataBinding()
                .withConversionService(conversionService)
                .build();
        Object currentValue = parsedPropertyNameExpression.getValue(evalContext, bean);
        System.out.println("old:" + currentValue);
        parsedPropertyNameExpression.setValue(evalContext, bean, expression);
        System.out.println("new:" + parsedPropertyNameExpression.getValue(evalContext, bean));
    }

    static class StringToMapConverter implements Converter<String, Map<String, String>> {

        private static final ObjectMapper objectMapper = new ObjectMapper();

        static {
            objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
        }

        @SuppressWarnings("unchecked")
        @Override
        public Map<String, String> convert(String source) {
            try {
                return this.objectMapper.readValue(source, LinkedHashMap.class);
            }
            catch (IOException e) {
                e.printStackTrace();
                throw new IllegalStateException(e);
            }
        }

    }

    static class Bean {

        private List<String> list = new ArrayList<>(Arrays.asList("foo", "bar"));

        private Map<String, String> map = new HashMap<>(Collections.singletonMap("foo", "bar"));

        public List<String> getList() {
            return this.list;
        }

        public void setList(List<String> list) {
            this.list = list;
        }

        public Map<String, String> getMap() {
            return this.map;
        }

        public void setMap(Map<String, String> map) {
            this.map = map;
        }

    }

}
 类似资料:
  • 问题内容: info.plist UIViewController 当我使用6p时,可以,但是 iphoneX不能调用,并且StatusBar不隐藏 问题答案: 您需要检查您的视图控制器是否包含在容器中(即 UINavigationController )。如果是这样,整个过程是这样的: 1)将 info.plist 文件中的View 值设置为YES 2)在您的子控制器中添加以下代码: 3)添加此

  • 我有一个代码片段,看起来像这样 配置类

  • 我的问题是:为什么我不能自动连接我的地图与接口,而我可以与实现? 多谢了。

  • 我现在的目标是创建一个网格,这将是我的游戏的基础。当玩家从菜单开始游戏时,这个网格应该出现在游戏场景上。稍后,我希望能够根据用户输入更改电路板的大小 1.在eventhandler中创建网格 我的推理是当玩家点击启动游戏的“SinglePlayer”按钮时创建网格。根据这个推理,我将简单地获取根节点(一个组)的子节点,并将gridpane添加到其中 为什么我被困住了 下面的代码段显示处理on bu

  • 问题内容: 这相当不错,但是我正在尝试学习/理解python中的函数式编程。如下代码: 产生: 问:有没有一种方法可以在python中使用map或任何其他功能工具来产生以下内容而没有循环等。 顺便提一下,如果foo和bar之间存在依赖关系,则实现将如何更改。 例如 并打印: PS:我知道如何使用if,循环和/或生成器天真地做到这一点,但是我想学习如何使用功能性工具来实现这一点。 这仅仅是在mapt

  • 所以我在ReactJS中做了一个排序可视化。 我有一个名为“bubblesort”的方法,它将遵循气泡排序算法对数组进行排序。 我有一个数组生成并在屏幕上可视化,名为“array”。 现在当我使用 它将对数组进行排序,并在每次加载页面时自动更改可视化数组。它不是我想要的,我想让它对数组进行排序,并在我单击按钮时改变可视化。所以我又做了一个这样的方法 并像这样调用按钮,它将对数组进行排序,但屏幕上的