【问题标题】:Spring SpEL - Expression Language to create Map of String and Custom ObjectSpring SpEL - 用于创建字符串和自定义对象映射的表达式语言
【发布时间】:2020-07-09 00:14:54
【问题描述】:

我正在使用 Spring Boot 示例从属性文件中读取以下内容。

sub.region.data={\
    AF: {'subRegionCd' : '34', 'subRegionName' : 'Southern Asia', 'subRegionDesc': '', 'status' : 'A'} \
}

我在下面用过,但是不行

@Value("#{${sub.region.data}}")
private Map<String, SubRegion> subRegionsMap; 

子区域.java

public class SubRegion {
    private String subRegionCd;
    private String subRegionName;
    private String subRegionDesc;
    private String subRegionStatus;
}

我遇到了错误

Caused by: org.springframework.beans.ConversionNotSupportedException: Failed to convert value of type 'java.util.Collections$UnmodifiableMap' to required type 'java.util.Map'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.util.Collections$UnmodifiableMap' to required type 'com.xxxxxx.model.SubRegion': no matching editors or conversion strategy found
    at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:76) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1195) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1167) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    ... 54 common frames omitted
Caused by: java.lang.IllegalStateException: Cannot convert value of type 'java.util.Collections$UnmodifiableMap' to required type 'com.xxxxxx.model.SubRegion': no matching editors or conversion strategy found
    at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:262) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.TypeConverterDelegate.convertToTypedMap(TypeConverterDelegate.java:608) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:182) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    at org.springframework.beans.TypeConverterSupport.convertIfNecessary(TypeConverterSupport.java:73) ~[spring-beans-5.1.5.RELEASE.jar:5.1.5.RELEASE]
    ... 57 common frames omitted

【问题讨论】:

    标签: spring spring-boot spring-el


    【解决方案1】:

    看来你在'subRegionDesc', 后面写错了,我想你的意思是使用冒号,而不是逗号

    对于spring boot,我建议你使用ConfigurationProperties,而不是@Value

    例如,在这种情况下,您必须:

    1. @EnableConfigurationProperties(SubRegionConfig.class) 放入您的弹簧配置类之一。

    2. 创建配置类:

      @ConfigurationProperties(prefix = "sub.region")
      public static class SubRegionConfig {
          private Map<String, SubRegion> data;
          //getters and setters
      } 
      
    3. 使用.yml 而不是.properties,就像这样:

      sub:
        region:
         data:
           AF:
            subRegionCd: '34'
            subRegionName: 'Southern Asia'
            subRegionDesc: ''
            subRegionStatus: 'A'
      
    4. 之后你可以从SubRegionConfing获得你想要的每一个属性

      @Autowired
      private SubRegionConfig subRegionConfig;
      

    ConfigurationsProperties 更复杂,但更灵活,更适合在大多数情况下使用。

    【讨论】:

    • 现在这给了我:Caused by: java.lang.IllegalStateException: Cannot convert value of type 'java.util.Collections$UnmodifiableMap' to required type 'com.XX.model.SubRegion': no matching editors or conversion strategy found
    • spring 期望您在地图中使用地图作为值,而不是 java bean (SubRegion)
    • 如果有多个 SubRegion ,如何根据场景动态取它们。
    【解决方案2】:

    #{} 运算符将数据发送到 spEL 解析器,这意味着它将尝试根据 spEL 语法将数据转换为其已知类型,如 Spring Docs 中的here 所示。

    发生的情况是编译器无法将任何数据转换为 SubRegion 对象:

    无法转换“java.util.Collections$UnmodifiableMap”类型的值 到所需类型“com.xxxxxx.model.SubRegion”:没有匹配的编辑器或 找到转化策略

    一个简单的解决方法是嵌套两个 Map 对象,这样您就可以在检索值后填充您的 SubRegion 对象。

    yourMap={'key1':{'nestedMapKey1:value', 'nestedMapKey2:value2'}}
    

    在带有代码的 .properties 文件中:

    sub.region.data={'AF':{'subRegionCd':'34', 'subRegionName':'Southern Asia', 'subRegionDesc':'', 'status':'A'}}
    

    然后,在您的代码中:

        @Value("#{${sub.region.data}}")
        private Map<String, Map<String, String>> subRegionsMap;
        // (...) handling the SubRegion
    

    我的 System.out.println(subRegionMap.get("AF"); 输出:

    {subRegionCd=34, subRegionName=Southern Asia, subRegionDesc=, status=A}
    

    【讨论】:

      猜你喜欢
      • 2013-12-10
      • 1970-01-01
      • 2014-01-14
      • 2018-06-09
      • 2014-07-30
      • 1970-01-01
      • 2020-06-03
      • 2023-03-28
      • 2011-10-04
      相关资源
      最近更新 更多