记一次SpringBoot2.x的@ImportResource和@PropertySource的前言中不允许有内容的坑
内容 一次 允许 SpringBoot2 前言
2023-06-13 09:14:31 时间
记一次SpringBoot2.x的@ImportResource和@PropertySource的坑
众所周知,SpringBoot提倡的是无配置文件,也就摒弃了以前用Spring时繁重的.xml配置文件,取而代之的使用SpringBoot特有的@Configuration注解的JavaConfig配置类。配置方式和XML配置方式几乎一一对应,少有区别。
那么当我们需要在SpringBoot中,需要使用XML配置文件,或者需要使用额外的.properties, .yml文件时,我们需要怎么做?
这时候就想到了几种方式:@ImportResource, @PropertySource
@ImportResource 是用于导入外部的.xml文件
@PropertySource 是用于导入变量类型的配置文件如.properties .yml
如果你用@ImportResource(locations = “xxx.yml”),通常情况你会得到这样的报错,
Caused by: org.xml.sax.SAXParseExcepton; lineNumber: 1; columnNumber: 1; 前言中不允许有内容 网上有大量关于这种错误的说法,但是绝大部分都是说你的文件编码格式有问题,需要转换。我在试过大量的方法后,还是不行,同时我也看到很多解决帖的下方留言,大多数都是留言不行,解决不了,我高度怀疑那些没质量的解决帖都是互相抄袭的。但是有一种方法我没有试,就是用notePad方式打开文件,然后保存为 UTF-8 with no BOM 的方式。
在尝试了很多次之后,我都无法通过@ImportResource的方式来导入外部.yml .properties配置文件,我也没有细心去查阅相关的源码,因此我转而关注@PropertySource来帮助我解决问题。
在使用@PropertySource的时候又发现了一个问题,它能正常帮助我导入.properties文件,我也能通过@ConfigurationProperties和@Value来得到配置文件中的相应变量值,但是它不能正确解读.yml文件。我想对于SpringBoot的常年开发者来说,早就已经把习惯改为用YML语言来书写配置文件,要换回使用properties虽然不麻烦,也有转换工具帮助,但是就不能有一种方法解决这个问题吗?
可喜可贺的是,@PropertySource里面有一个属性叫factory,默认实现类是DefaultPropertySourceFactory,这个factory的作用是解析配置文件,因此简单翻阅了DefaultPropertySourceFactory的源码,发现它对yml的支持非常鸡肋,默认是只能解析.properties文件。因此我对其做了扩展,让其在解析配置文件的时候,判断配置文件是.properties还是.yml,然后走相应的解析逻辑。
/**
* 该类是扩展{@link org.springframework.core.io.support.DefaultPropertySourceFactory}的,
* 用于{@link org.springframework.context.annotation.PropertySource}的factory属性。
*
* @PropertySource的facotroy属性,默认是使用 DefaultPropertySourceFactory 实现。该实现只能解析.properties配置文件,
* 因此.yml文件无法解析。
*
*/
public class YmlPropertiesFactory 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();
}
}
@PropertySource(value = {"classpath:dy.yml"}, ignoreResourceNotFound = true, factory = YmlPropertiesFactory.class)
好了,现在你就能正常解析YML文件
小结:
(1) 如果你要导入外部XML文件,用@ImportResource (2) 如果你要导入的是.properties .yml这样的配置文件,用@PropertySource
或许我的总结是错误的,但就目前来看,这样能够解决SpringBoot导入外部配置文件时的问题,或许ImportResource也能导入.properties .yml文件,只是我方式用错了,如果有深入研究的过的朋友,可以在下方留言为社区贡献一份力量。
相关文章
- Linux—文本内容管理和文件查找
- Flask 学习-45.Flask-RESTX 自定义参数校验和自定义错误内容 error_msg 使用
- 将 SAP ABAP 内表内容本地导出成 Excel 文件试读版
- 从第一性原理出发,分析 AI 会如何改变视觉内容的创作和分发
- Drupal v8.3.0 发布,一个内容管理系统详解编程语言
- MySQL中内容含有斜杠的处理方法(mysql 中内容有斜杠)
- 列内容如何在Oracle中查找重复列内容(oracle中怎么查重复)
- 提升页面加载速度Redis缓存技术何时上场(redis缓存页面内容)
- asp下实现截取字符串特定部分内容函数
- SQLServer中通过reverse取某个最后一次出现的符号后面的内容(字符串反转)