Properties文件和Yml文件数据解析

/ 默认分类 / 0 条评论 / 2327浏览
    @Test
    public void test(){
        Map<String, Map<String, String>> maps = testConfig.getMaps();
        System.out.println(maps);
    }
@Configuration
@RefreshScope
public class TestConfig {

    @Value("#{${config.testMaps}}")
    private Map<String, Map<String,String>> maps;

}

application.properties

config.testMaps:"{GOPAY: {switch:'1',INTEREST_GOT:'M0240'}, AGENT: {switch:'1',INTEREST_GOT:'M0274',ACCOUNT_OPEN_SUCC:'M0273'}}"

执行结果:

nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'scopedTarget.okCardConfig': Unsatisfied dependency expressed through field 'maps'; nested exception is org.springframework.beans.ConversionNotSupportedException: Failed to convert value of type 'java.lang.String' to required type 'java.util.Map'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'java.util.Map': no matching editors or conversion strategy found
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject

将application.properties内容修改为

config.testMaps="{GOPAY: {switch:'1',INTEREST_GOT:'M0240'}, AGENT: {switch:'1',INTEREST_GOT:'M0274',ACCOUNT_OPEN_SUCC:'M0273'}}"

同样报错;

将application.properties内容修改为

config.testMaps="{GOPAY: {switch:'1',INTEREST_GOT:'M0240'}, AGENT: {switch:'1',INTEREST_GOT:'M0274',ACCOUNT_OPEN_SUCC:'M0273'}}"

同样报错;

将application.properties内容修改为

config.testMaps={GOPAY: {switch:'1',INTEREST_GOT:'M0240'}, AGENT: {switch:'1',INTEREST_GOT:'M0274',ACCOUNT_OPEN_SUCC:'M0273'}}

正常

{GOPAY={switch=1, INTEREST_GOT=M0240}, AGENT={switch=1, INTEREST_GOT=M0274, ACCOUNT_OPEN_SUCC=M0273}}

将application.properties内容修改为

config.testMaps:{GOPAY: {switch:'1',INTEREST_GOT:'M0240'}, AGENT: {switch:'1',INTEREST_GOT:'M0274',ACCOUNT_OPEN_SUCC:'M0273'}}

正常

{GOPAY={switch=1, INTEREST_GOT=M0240}, AGENT={switch=1, INTEREST_GOT=M0274, ACCOUNT_OPEN_SUCC=M0273}}

如果是application.yml

config:
  testMaps: "{GOPAY: {switch:'1',INTEREST_GOT:'M0240'}, AGENT: {switch:'1',INTEREST_GOT:'M0274',ACCOUNT_OPEN_SUCC:'M0273'}}"

正常

{GOPAY={switch=1, INTEREST_GOT=M0240}, AGENT={switch=1, INTEREST_GOT=M0274, ACCOUNT_OPEN_SUCC=M0273}}

解释:

application.properties配置文件内同如下:

zh54cn.saving.push.config: {GOPAY: {switch:'1',INTEREST_GOT:'M0240'}, AGENT: {switch:'1',INTEREST_GOT:'M0274',ACCOUNT_OPEN_SUCC:'M0273'}}
zh54cn.saving.push.config1: "{GOMPAY: {switch:'1',INTEREST_GOT:'M0240'}, AGENT: {switch:'1',INTEREST_GOT:'M0274',ACCOUNT_OPEN_SUCC:'M0273'}}
zh54cn.saving.push.config2: 100
zh54cn.saving.push.config3: "100"
zh54cn.saving.push.config4: true
zh54cn.saving.push.config5: "true"

执行后解析的properties文件值如下:

所以,可以理解为properties配置文件的配置值默认就是解析为字符串类型,然后按照程序中的接收类型来进行转换,所以properties文件配置值不需要添加引号注明字符串,否则就会出现上面的问题,导致解析到的数据有问题。

所以下面这样都是报错

zh54cn.saving.push.config:"100"
    @Value("${zh54cn.saving.push.config}")
    private int savingPushConfig1;
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'scopedTarget.okCardConfig': Unsatisfied dependency expressed through field 'savingPushConfig1'; nested exception is org.springframework.beans.TypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'int'; nested exception is java.lang.NumberFormatException: For input string: ""100""
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject

zh54cn.saving.push.config:"gopay"
    @Value("${zh54cn.saving.push.config}")
    private String savingPushConfig1;
System.out.println(testConfig);
savingPushConfig1="gopay"

可以看到,多了一个双引号,等于转义了.


zh54cn.saving.push.config:gopay
    @Value("${zh54cn.saving.push.config}")
    private String savingPushConfig1;
        System.out.println(testConfig);
savingPushConfig1=gopay

这样toString打印得到的就是正常的了.


综上,记住一点,properties文件默认读取解析为字符串,之后springbean包中的数据注入逻辑按照相应的接收对象类型来转换.

yml文件有所不同,如下:

application.yml文件:

gopay.saving.push.config: 100
gopay.saving.push.config1: "100"
gopay.saving.push.config2: "sss"
gopay.saving.push.config3: sss
gopay.saving.push.config4: true
gopay.saving.push.config5: "true"

可以看出来,properties文件直接解析为Properties类,并且hasshtable的key和value都解析为String

class Properties extends Hashtable<Object,Object>

yml文件是解析为LinkedHashMap,并且key解析为字符串,但是配置的值是按照实际配置的数据值的类型进行解析的.比如引号中的就一定是字符串类型,单独的true或false就是布尔类型,单独的数字就是整形,这一点可以按照和json数据格式的数据类型来理解,基本一致. 所以,properties文件解析为字符串,yml解析按照实际类型解析.

实际上,无论properties,yml还是json还是xml,这些都是属于明确的一种数据交换格式,他们有自己的语法标识各类数据类型,只不过支持的数据类型不同,所以有以上区别.