@PropertySource指定文件地址
@ConfigurationProperties指定前缀。
第一次:
SpringBoot 读取配置文件
demo如下:
designers.yml文件
designer:
owner:
openids:
- 8hV+lc6uYmfnXlfrVh52j0wBH6QOrs7Cyo/WM3SaHLA=
- 3g+vDhtKqRHf97zKoJ8K0eSnv6hX4dLcNHXvDKxdb28=
- 3e0EHRNifV73VxAjq6269j98NupXr8yjEgpUfiGb+g8=
- kEPoIITwJePavbYUAsM/uPRJioi/ueApxPFulw6s/eM=
usernames:
- liming
- xiaohong
- zam
- zqm
config配置:
/**
* 配置表
*
* @date:2018/12/12
* @author zqm
*/
@ConfigurationProperties(prefix = "designer")
@Component
public class DesignProperties {
private Map<String, List<String>> owner;
public Map<String, List<String>> getOwner() {
return owner;
}
public void setOwner(Map<String, List<String>> owner) {
this.owner = owner;
}
}
测试demo:
@RequestMapping("/test")
public String test() {
Map<String, List<String>> map = designProperties.getOwner();
List<String> ids= map.getOrDefault("openids", Arrays.asList("fail"));
return JSON.toJSONString(ids);
}
结果狠狠的打了一把脸!竟然是500!,NPE.
map是个空问题出在配置文件类上,咋回事呢?然后打断点到配置文件,发现启动初始化的时候根本没有进来,擦,问题出在读取文件上,文件读取不成功,特意百度了一下,没写错啊,我看别人是properties文件,这个注解PropertySource还难道不支持yml,搞什么✈️啊,进了源码看下,看到有个默认factory,
package org.springframework.context.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.io.support.PropertySourceFactory;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(PropertySources.class)
public @interface PropertySource {
/**
* Indicate the name of this property source. If omitted, a name will
*/
String name() default "";
/**
* Indicate the resource location(s) of the properties file to be loaded. 指定资源地址
*/
String[] value();
/**
* Indicate if failure to find the a {@link #value() property resource} should be
* ignored.
* <p>{@code true} is appropriate if the properties file is completely optional.
* Default is {@code false}.
* @since 4.0
*/
boolean ignoreResourceNotFound() default false;
/**
* A specific character encoding for the given resources, e.g. "UTF-8".
* @since 4.3
*/
String encoding() default "";
/**
* Specify a custom {@link PropertySourceFactory}, if any.
* <p>By default, a default factory for standard resource files will be used.
* @since 4.3
* @see org.springframework.core.io.support.DefaultPropertySourceFactory
* @see org.springframework.core.io.support.ResourcePropertySource
*/
Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;
}
因此:我看了下PropertySourceFactory只有一个默认的实现
而这个PropertySourceFactory工厂只处理properties配置文件,既然这样得自己定义实现一个YamFactory了。
第二次:
修改后的配置文件:
/**
* 配置表
*
* @author zqm
* @date:2018/12/12
*/
@PropertySource(value = "classpath:designers.yml", factory = yamFactory.class)
@ConfigurationProperties(prefix = "designer")
@Component
@Data
public class DesignProperties {
private Map<String, List<String>> owner;
}
yml工厂类:
package com.zqm.config;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.DefaultPropertySourceFactory;
import org.springframework.core.io.support.EncodedResource;
import java.io.IOException;
import java.util.Optional;
import java.util.Properties;
/**
* @describe:
* @author:zqm
*/
public class YamFactory extends DefaultPropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource)
throws IOException {
String sourceName = Optional.ofNullable(name).orElse(resource.getResource().getFilename());
if (!resource.getResource().exists()) {
// return an empty Properties
return new PropertiesPropertySource(sourceName, new Properties());
} else if (sourceName.endsWith(".yml") || sourceName.endsWith(".yaml")) {
Properties propertiesFromYaml = loadYaml(resource);
return new PropertiesPropertySource(sourceName, propertiesFromYaml);
} else {
return super.createPropertySource(name, resource);
}
}
/**
* load yaml file to properties
*
* @param resource
* @return
* @throws IOException
*/
private Properties loadYaml(EncodedResource resource) throws IOException {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(resource.getResource());
factory.afterPropertiesSet();
return factory.getObject();
}
}
结果:读取了配置文件内容,哈哈哈哈!爽
总结:
@ConfigurationProperties有的版本里面有
location属性可以直接指定文件地址,貌似后面没有了。
@PropertySource 的factory属性默认解析的propertie文件。
因此读取yml文件需要自定义工厂。
学习一个注解类是,还是要多多看看源码显示其各个属性含义,看不懂也得去百度啊。靠着之前的经验会一脸懵逼,有些注解版本更新还蛮大的。
附录1基本类型的配置文件格式:
aalist:
#对应字符串
name: zha
#对用list
myList:
- a
- b
#对应数组
arrays: 1,2,3
#对应map
valueMap:
name: zqm
age: 20
sex: male
#对应list<map>
mapList:
- name: mm
age: 21
- name: ll
age: 22
config文件:
/**
* Copyright (C) 2006-2019 Tuniu All rights reserved
*/
package com.zqm.service;
import com.zqm.config.YamFactory;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
/**
* ConfigurationProperties 注入一个类,对象 --支持宽松绑定
* 1.5之前还有location属性,指定文件 代替方案@PropertySource
* prefix前缀定义了哪些外部属性将绑定到类的字段上
* ignoreInvalidFields 设置为true 绑定失败程序不会报错
* 根据 Spring Boot 宽松的绑定规则,类的属性名称必须与外部属性的名称匹配
* 我们可以简单地用一个值初始化一个字段来定义一个默认值
* 类本身可以是包私有的
* 类的字段必须有公共 setter 方法
* <p>
* <p>
* Value("${zk.register.merinfo}") 注入地址等简单方式
*
* @author zhaqianming
* <p>
* Date: 2019-11-05
*/
@Component
@PropertySource(value = "classpath:aalist.yml",factory = YamFactory.class)
@ConfigurationProperties(prefix = "aalist")
@Data
public class YamlTestAaList {
private String name;
private List<String> myList;
private Integer [] arrays;
private Map<String,String> valueMap;
private List<Map<String,String>> mapList;
private Map<Integer,Integer> moduleCategoryMap;
}
附录2springboot读取properties文件:
list.properties:
#map 第一种形式
data.person.name=zam
data.person.sex=man
data.person.age=28
data.person.hight=170
#map 第二种形式
data.student[name]=zqm
data.student[age]=18
data.student[no]=004
#list 第一种方式
data.list[0]=list1
data.list[1]=list2
data.list[2]=list3
#list 第二种方式
data.newList=list4,list5,list5
读取配置代码:
package com.zqm.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
/**
* @describe:
* @author:zqm
*/
@PropertySource(value = "classpath:list.properties")
@ConfigurationProperties(prefix = "data")
@Component
@Data
public class ListProperties {
private Map<String,String> student;
private Map<String,String> person;
private List<String> list;
private List<String> newList;
}
debug启动的结果如下: