从 Java 中的 yaml 读取地图变为空

2022-01-14 00:00:00 dictionary yaml spring java

我在使用 spring 通过 java 读取我的 yaml 时遇到问题.让我先显示代码

I am getting a problem in reading my yaml through java, using spring. Let me show the code first

@Component
@EnableConfigurationProperties
@ConfigurationProperties(prefix = "countries")
public class UserLimitReader {

    private HashMap<String, Integer> orders;

    private HashMap<String, Integer> requests;

    public HashMap<String, Integer> getOrders() {
        return orders;
    }

    public void setOrderRedeemableLimit(HashMap<String, Integer>         orders) 
{
        this.orders= orders;
}

public HashMap<String, Integer> getRequests() {
    return requests;
}

public void setMonthlyRedeemableLimit(HashMap<String, Integer> requests) {
    this.requests= requests;
}
}

我的 yaml 文件:

My yaml file:

cassandra:
    hosts: localhost:9142, 127.0.0.1:9142
    keyspace: test
countries:
    orders:
      JPY: 1000
      USD: 1000
    requests:
      JPY: 100000
      USD: 100000

spring上下文xml也有这个:

The spring context xml also has this:

<bean id="yamlProperties"
    class="org.springframework.beans.factory.config.YamlPropertiesFactoryBean">
    <property name="resources">
        <value>classpath:config/application.yaml</value>
    </property>
</bean>

<context:property-placeholder
    properties-ref="yamlProperties" />

现在,我的期望是,在我的 spring-test 应用程序运行时(上下文 xml 来自我的测试资源,yaml 也在我的测试中),这些订单和请求的值已设置,但它们为空.另外,请注意,除了我使用 @Value(${...}) 注入的这些值之外,我的 yaml 中还有其他值,它们被注入绝对没问题!

Now, the expectation that I have(had) is that, during the runtime of my spring-test application(the context xml is from my test resources, the yaml is also in my test), these values of orders and requests are set, but they are null. Also, note, there are other values in my yaml besides this that I am injecting using @Value(${...}), they are injected absolutely fine!

我看了这个:Spring Boot - 从应用程序.yml

我做了几乎相同的事情,但是我的价值观还没有设定.请帮忙.

I have done virtually the same, but yet, my values are not set. Kindly help.

我正在通过谷歌,找到这个链接:http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/config/YamlPropertiesFactoryBean.html

I was going through google, found this link: http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/config/YamlPropertiesFactoryBean.html

在这里,它说,所有内容都被读取为字符串而不是映射.是否有任何其他类支持读取 Yaml 文件,就像他们在这里所做的那样:Spring Boot - 从 application.yml 注入映射

In this, it says, everything is read as a string and not a map. Is there any other class that supports reading of Yaml file the way they did it here: Spring Boot - inject map from application.yml

还是我对 YamlPropertiesFactoryBean 的理解有误?

Or is my understanding of YamlPropertiesFactoryBean wrong?

compile 'org.springframework:spring-core:4.2.+'
compile 'org.springframework:spring-beans:4.2.+'
compile 'org.springframework:spring-context:4.2.+'
compile 'org.springframework.boot:spring-boot:1.3.1.RELEASE'
compile 'org.springframework.boot:spring-boot-configuration-processor:1.3.1.RELEASE'

这些是 gradle 中的依赖项.你可能想知道为什么我有 spring-core 和 spring-boot,本质上,我不想要 spring-boot,但是没有 spring-boot,我不能添加 @EnableConfigurationProperties 和 @ConfigurationProperties,我真的不知道我是否可以在没有它们的情况下将 yaml 内容读入地图.因此添加了这两个依赖项,但如果有办法删除它们,我会非常乐意删除这两个依赖项.

These are the dependencies in gradle. You might be wondering why I have spring-core and spring-boot, essentially, I don't want spring-boot, but without spring-boot, I don't get to add @EnableConfigurationProperties and @ConfigurationProperties, I honestly don't know if I can read the yaml content into a map without them. Hence those two dependencies are added, but if there's a way to remove them, I would be more than happy to remove those two dependencies.

热烈的问候,帕万

推荐答案

我在使用不同的泛型时遇到了同样的问题,我通过初始化map成员并删除setter方法来解决它,例如:

I had the same problem with different generic types and I solved it by initializing the map member and remove the setter method, e.g.:

@Component
@EnableConfigurationProperties
@ConfigurationProperties(prefix = "countries")
public class UserLimitReader{
    private Map<String, Integer> orders = new HashMap<>();

    private Map<String, Integer> requests = new HashMap<>();

    public Map<String, Integer> getOrders() {
        return orders;
    }
    ...
}

请注意,我使用了 java 7 菱形运算符并将成员类型更改为 Map 而不是 HashMap.

Please note I used java 7 diamond operator and change the member type to Map instead of HashMap.

重要提示:在我的代码中,我使用 Spring 的配置类而不是 XML,并将 EnableConfigurationProperties 移动到配置类.在你的情况下,它应该是这样的:

IMPORTANT: In my code, I use Spring's configuration class instead of XML and moved the EnableConfigurationProperties to the configuration class. In your case it should be something like:

@Configuration
@EnableConfigurationProperties(value = {UserLimitReader.class})
public class SpringConfiguration {
    ...
}

@ConfigurationProperties(prefix = "countries", locations: "classpath:config/application.yaml")
public class UserLimitReader {
    ...
}

不知道你如何使用 XML 配置它,但是正如我在评论中所写的,我仍然认为你应该确保 Spring 使用组件扫描或类似的方法找到你的类.

Don't know how you configure it using XML, however as I wrote in my comments I still think you should make sure Spring's finds your class using component scan or something alike.

@Value 在 Spring 使用您的上下文文件加载 YAML 文件时正常工作,但这并不意味着 UserLimitReader 文件由 Spring 加载和配置.

@Value work as Spring loads the YAML file without any problem using your context file, however it does not mean UserLimitReader file is loaded and configured by Spring.

相关文章