springboot 自定义属性文件拓展名(PropertySourceLoader)
*********************
相关类与接口
PropertySourceLoader
public interface PropertySourceLoader {
String[] getFileExtensions();
List<PropertySource<?>> load(String name, Resource resource) throws IOException;
}
PropertiesPropertySourceLoader
public class PropertiesPropertySourceLoader implements PropertySourceLoader {
private static final String XML_FILE_EXTENSION = ".xml";
public PropertiesPropertySourceLoader() {
}
public String[] getFileExtensions() {
return new String[]{"properties", "xml"};
} //加载properties、xml后缀的属性文件
public List<PropertySource<?>> load(String name, Resource resource) throws IOException {
List<Map<String, ?>> properties = this.loadProperties(resource);
//加载属性文件
if (properties.isEmpty()) {
return Collections.emptyList();
} else {
List<PropertySource<?>> propertySources = new ArrayList(properties.size());
for(int i = 0; i < properties.size(); ++i) {
String documentNumber = properties.size() != 1 ? " (document #" + i + ")" : "";
propertySources.add(new OriginTrackedMapPropertySource(name + documentNumber, Collections.unmodifiableMap((Map)properties.get(i)), true));
} //转换为List<PropertySource<?>>
return propertySources;
}
}
private List<Map<String, ?>> loadProperties(Resource resource) throws IOException {
String filename = resource.getFilename();
List<Map<String, ?>> result = new ArrayList();
if (filename != null && filename.endsWith(".xml")) {
result.add(PropertiesLoaderUtils.loadProperties(resource));
} else {
List<Document> documents = (new OriginTrackedPropertiesLoader(resource)).load();
documents.forEach((document) -> {
result.add(document.asMap());
});
}
return result;
}
}
YamlPropertySourceLoader
public class YamlPropertySourceLoader implements PropertySourceLoader {
public YamlPropertySourceLoader() {
}
public String[] getFileExtensions() {
return new String[]{"yml", "yaml"};
} //加载yml、yaml后缀的属性文件
public List<PropertySource<?>> load(String name, Resource resource) throws IOException {
if (!ClassUtils.isPresent("org.yaml.snakeyaml.Yaml", this.getClass().getClassLoader())) {
throw new IllegalStateException("Attempted to load " + name + " but snakeyaml was not found on the classpath");
} else {
List<Map<String, Object>> loaded = (new OriginTrackedYamlLoader(resource)).load();
//加载属性文件
if (loaded.isEmpty()) {
return Collections.emptyList();
} else {
List<PropertySource<?>> propertySources = new ArrayList(loaded.size());
for(int i = 0; i < loaded.size(); ++i) {
String documentNumber = loaded.size() != 1 ? " (document #" + i + ")" : "";
propertySources.add(new OriginTrackedMapPropertySource(name + documentNumber, Collections.unmodifiableMap((Map)loaded.get(i)), true));
} //转换为List<PropertySource<?>>
return propertySources;
}
}
}
}
PropertySource
public abstract class PropertySource<T> {
protected final Log logger;
protected final String name;
protected final T source;
public PropertySource(String name, T source) {
this.logger = LogFactory.getLog(this.getClass());
Assert.hasText(name, "Property source name must contain at least one character");
Assert.notNull(source, "Property source must not be null");
this.name = name;
this.source = source;
}
public PropertySource(String name) {
this(name, new Object());
}
public String getName() {
public T getSource() {
public boolean containsProperty(String name) {
return this.getProperty(name) != null;
}
@Nullable
public abstract Object getProperty(String var1);
public boolean equals(@Nullable Object other) {
public int hashCode() {
public String toString() {
public static PropertySource<?> named(String name) {
return new PropertySource.ComparisonPropertySource(name);
}
**********
内部类:ComparisonPropertySource
static class ComparisonPropertySource extends PropertySource.StubPropertySource {
private static final String USAGE_ERROR = "ComparisonPropertySource instances are for use with collection comparison only";
public ComparisonPropertySource(String name) {
super(name);
}
public Object getSource() {
throw new UnsupportedOperationException("ComparisonPropertySource instances are for use with collection comparison only");
}
public boolean containsProperty(String name) {
throw new UnsupportedOperationException("ComparisonPropertySource instances are for use with collection comparison only");
}
@Nullable
public String getProperty(String name) {
throw new UnsupportedOperationException("ComparisonPropertySource instances are for use with collection comparison only");
}
}
**********
内部类:StubPropertySource
public static class StubPropertySource extends PropertySource<Object> {
public StubPropertySource(String name) {
super(name, new Object());
}
@Nullable
public String getProperty(String name) {
return null;
}
}
}
OriginTrackedMapPropertySource
public final class OriginTrackedMapPropertySource extends MapPropertySource implements OriginLookup<String> {
private final boolean immutable; //默认为false
public OriginTrackedMapPropertySource(String name, Map source) {
this(name, source, false);
}
public OriginTrackedMapPropertySource(String name, Map source, boolean immutable) {
super(name, source);
this.immutable = immutable;
}
public Object getProperty(String name) {
public Origin getOrigin(String name) {
public boolean isImmutable() {
*********************
示例:自定义加载json后缀的属性文件加载器
*****************
配置文件
application.json
{
"person.name": "瓜田李下",
"person.age": 20
}
*****************
pojo 层
Person
@Data
@Component
@ConfigurationProperties("person")
public class Person {
private String name;
private Integer age;
}
*****************
config 层
CustomPropertySource
public class CustomPropertySourceLoader implements PropertySourceLoader {
@Override
public String[] getFileExtensions() {
return new String[]{"json"};
}
@Override
public List<PropertySource<?>> load(String name, Resource resource) throws IOException {
Map<String,Object> map=JSONObject.parseObject(IOUtils.toString(resource.getInputStream(), Charset.defaultCharset())).getInnerMap();
if (map==null||map.size()==0){
return Collections.emptyList();
}else {
return Collections.singletonList(new OriginTrackedMapPropertySource(name,map));
}
}
}
src/main/resources下新建目录/META-INF,创建文件spring.factories
spring.factories
org.springframework.boot.env.PropertySourceLoader=\
com.example.demo.config.CustomPropertySourceLoader
*****************
controller 层
HelloController
@RestController
public class HelloController {
@Resource
private Person person;
@RequestMapping("/hello")
public Person hello(){
System.out.println(person);
return person;
}
}
*********************
使用测试
localhost:8080/hello,控制台输出
2021-09-19 15:48:22.423 INFO 7952 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2021-09-19 15:48:22.434 INFO 7952 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 11 ms
Person(name=瓜田李下, age=20)