我们在开发springboot的项目过程中,为了不把所有的配置信息全都写在application.(yml/properties)中,我们需要自定义配置文件比如common.properties,那么问题来了,我们要如何读取common.properties里面的内容。
也许有小伙伴会说那还不简单,直接写个读取配置文件工具类来读取不就行了。这样确实可以满足需求,但有没有更优雅的读取方法,比如用springboot提供的@Value注解就可以取到配置信息,而非用PropertiesUtil.getProperty("abc")方式来获取。
答案是有的,以下介绍两种方案实现用@value来获取自定义配置文件
@PropertySource可以用来加载指定的配置文件,默认它只能加载*.properties文件,不能加载诸如yaml等文件。
@PropertySource相关属性介绍
示例
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Configuration
@PropertySource(value = {"classpath:common.properties"},ignoreResourceNotFound=false,encoding="UTF-8")
@ConfigurationProperties(prefix = "author")
public class Author {
private String name;
private String job;
private String sex;
}
有小伙伴也许发现示例上的@ConfigurationProperties注解了。当我们使用@Value需要注入的值较多时,代码就会显得冗余。我们可以使用@ConfigurationProperties 中的 prefix 用来指明我们配置文件中需要注入信息的前缀
前边提到了用@PropertySource只能加载*.properties文件,但如果我们项目的配置文件不是*.properties这种类型,而是其他类型,诸如yaml,此时我们可以通过实现PropertySourceFactory接口,重写createPropertySource方法,就能实现用@PropertySource也能加载yaml等类型文件。
示例代码
public class YamlPropertySourceFactory implements PropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String sourceName, EncodedResource resource) throws IOException {
Properties propertiesFromYaml = loadYaml(resource);
if(StringUtils.isBlank(sourceName)){
sourceName = resource.getResource().getFilename();;
}
return new PropertiesPropertySource(sourceName, propertiesFromYaml);
}
private Properties loadYaml(EncodedResource resource) throws FileNotFoundException {
try {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(resource.getResource());
factory.afterPropertiesSet();
return factory.getObject();
} catch (IllegalStateException e) {
// for ignoreResourceNotFound
Throwable cause = e.getCause();
if (cause instanceof FileNotFoundException)
throw (FileNotFoundException) e.getCause();
throw e;
}
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Configuration
@PropertySource(factory = YamlPropertySourceFactory.class,value = {"classpath:user.yml"},ignoreResourceNotFound=false,encoding="UTF-8")
@ConfigurationProperties(prefix = "user")
public class User {
private String username;
private String password;
}
其实现流程如下:
1、实现EnvironmentPostProcessor接口,重写postProcessEnvironment方法
@Slf4j
public class CustomEnvironmentPostProcessor implements EnvironmentPostProcessor {
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
Properties properties = new Properties();
try {
properties.load(new InputStreamReader(CustomEnvironmentPostProcessor.class.getClassLoader().getResourceAsStream("custom.properties"),"UTF-8"));
PropertiesPropertySource propertiesPropertySource = new PropertiesPropertySource("custom",properties);
environment.getPropertySources().addLast(propertiesPropertySource);
} catch (IOException e) {
log.error(e.getMessage(),e);
}
}
}
2、在META-INF下创建spring.factories
spring.factories文件内容如下:
org.springframework.boot.env.EnvironmentPostProcessor=com.github.lybgeek.env.CustomEnvironmentPostProcessor
1、2步骤实现完后,就可以在代码中直接用@Value的方式获取自定义配置文件内容了
读取的自定义配置文件内容的实现方法有多种多样,除了上面的方法,还可以在以-jar方式启动时,执行形如下命令
java -jar project.jar --spring.config.location=classpath:/config/custom.yml
也能实现。还可以干脆自定义配置文件都以application-*为前缀,比如application-custom,然后在application.properties,使用spring.profiles.include=custom或者spring.profiles.active=custom也可以实现
https://github.com/lyb-geek/springboot-learning/tree/master/springboot-outside-config