SpringBoot如何加载jar包外面的配置文件
两种情况:
1.在填充普通bean属性之前加载
2.在初始化之后,填充普通bean属性加载
3.通过System.setProperty() 来设置获取
先清楚一个问题:扫描策略(涉及到覆盖优先级问题)
配置文件位置及加载顺序
SpringBoot 项目中的application.properties配置文件一共可以出现在如下4个位置:
顺序:高-》低
项目根目录下的config文件夹
项目根目录下
classpath下的config文件夹
classpath下
优先级由高到底,高优先级的配置会覆盖低优先级的配置;
SpringBoot会从这四个位置全部加载主配置文件;互补配置;
我们还可以通过spring.config.location来改变默认的配置文件位置
在运行时再指定配置文件的名字。使用spring.config.location可以指定配置文件所在目录
指定配置文件和默认加载的这些配置文件共同起作用形成互补配置;
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config.location=G:/application.properties
情况1 :在填充普通bean属性之前加载
springBoot的EnvironmentPostProcessor使用
SpringBoot支持动态的读取文件,留下的扩展接口org.springframework.boot.env.EnvironmentPostProcessor。这个接口是spring包下的,使用这个进行配置文件的集中管理,而不需要每个项目都去配置配置文件。这种方法也是springboot框架留下的一个扩展(可以自己去扩展)
使用步骤
介绍:即在加载resource 下的application.yml文件之前加载外部文件到环境中environment
步骤一:
/**
*
*自定义环境处理,在运行SpringApplication之前加载任意配置文件到Environment环境中
* @author sunrj
* @create 2021-07-06 13:48
*/
public class CustomEnvironmentPostProcessor implements EnvironmentPostProcessor,Ordered {
private static final Integer POST_PROCESSOR_ORDER = Integer.MAX_VALUE+10;
@Override
public int getOrder() {
return -this.POST_PROCESSOR_ORDER;
}
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment,SpringApplication application) {
//自定义配置文件
//自定义配置文件
String[] profiles = {
"xxx.properties",
"yyy.properties",
"zzz.yml",
};
//循环添加
for (String profile : profiles) {
//从classpath路径下面查找文件
// Resource resource = new ClassPathResource(profile);
//从自定义文件夹下找
Resource resource = new PathResource("/adc-cms/repository/"+profile);
//加载成PropertySource对象,并添加到Environment环境中
environment.getPropertySources().addLast(loadProfiles(resource));
}
}
//加载单个配置文件
private PropertySource<?> loadProfiles(Resource resource) {
if (!resource.exists()) {
throw new IllegalArgumentException("资源" + resource + "不存在");
}
try {
YamlPropertySourceLoader sourceLoader = new YamlPropertySourceLoader();
List<PropertySource<?>> propertySources = sourceLoader.load(resource.getFilename(), resource);
return propertySources.get(0);
}catch (IOException ex) {
throw new IllegalStateException("加载配置文件失败" + resource, ex);
}
}
}
步骤二、
接口的实现类必须在META-INF/spring.factories文件中注册,使用EnvironmentPostProcessor 的全类名当key,实现类的全类名当value。resources目录下新建META-INF/spring.factories文件,添加如下内容。
在\resources\META-INF\spring.factories添加:
## 启用我们的自定义环境处理类
org.springframework.boot.env.EnvironmentPostProcessor=com.confs.config.CustomEnvironmentPostProcessor
在启动类中测试运行:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
System.out.println(context.getEnvironment().getProperty("file.property"));
System.out.println(context.getEnvironment().getProperty("file.list"));
context.close();
}
}
情况2:在初始化之后,填充普通bean属性加载
@PropertySource能够“扫描”和加载jar包外面的properties文件,但扫描不到yml
yml做法:
@ConfigurationProperties(prefix = "admin")
@Configuration
@NoArgsConstructor
@Getter
@Setter
public class AdminAuthProperties {
private AuthMethod[] loginMethodLimit;
private AccountLockingPolicyProperties lockingPolicy;
private List<String> loginNameFields;
private String publicKey;
private String privateKey;
//加载外部配置
@Bean
public static PropertySourcesPlaceholderConfigurer loadProperties() {
PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
yaml.setResources(new PathResource("./repository/cms.yml"));//class路径引入
configurer.setProperties(yaml.getObject());
return configurer;
}
}
properties做法:
通过@PropertySource注解将properties配置文件中的值存储到Spring的 Environment中,Environment接口提供方法去读取配置文件中的值,参数是properties文件中定义的key值。
在@ConfigurationProperties注释中有两个属性:
locations:指定配置文件的所在位置
prefix:指定配置文件中键名称的前缀(我这里配置文件中所有键名都是以author.开头)
使用@Component是让该类能够在其他地方被依赖使用,即使用@Autowired注释来创建实例。
创建测试Controller
@PropertySource和@Value
创建java配置类
@Configuration
@PropertySource(value = {
"classpath:xxx.properties",
"classpath:yyy.properties",
"classpath:zzz.yml",},encoding = "utf-8")
public class PropertiesWithJavaConfig {
@Value(${jdbc.driver})
private String driver;
@Value(${jdbc.url})
private String url;
@Value(${jdbc.username})
private String username;
@Value(${jdbc.password})
private String password;
//要想使用@Value 用${}占位符注入属性,这个bean是必须的,这个就是占位bean,另一种方式是不用value直接用Envirment变量直接getProperty('key')
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
情况3:通过System.setProperty() 来设置获取
可在启动类中,把需要加载的文件通过以下方式存起来:
System.setProperty(固定值,加载的文件路径)
System.setProperty("spring.config.location","D:\\project\\other-project\\\repository\\application.yml");
System.setProperty("Property2","def");
//这样就把第一个参数设置成为系统的全局变量!可以在项目的任何一个地方 通过System.getProperty("变量");来获得,
//System.setProperty 相当于一个静态变量 ,存在内存里面!