# 1. 配置文件 ## 1.1 外部載入順序 1. 命令行參數 java -jar spring-boot-02-config-02.0.0.1-SNAPSHOT.jar --server.port=8087 java -jar spring-boot-02-config-02.0.0.1-SNA ...
1. 配置文件
1.1 外部載入順序
-
命令行參數
java -jar spring-boot-02-config-02.0.0.1-SNAPSHOT.jar --server.port=8087 java -jar spring-boot-02-config-02.0.0.1-SNAPSHOT.jar --spring.profiles.active=prod
-
來自java:comp/env的NDI屬性
-
Java系統屬性(System.getProperties() )
-
操作系統環境變數
-
RandomValuePropertySource配置的random.*屬性值
-
jar包外部的
application-{profile}.properties
或application.yml
(帶spring.profile)配置文件-hello |- a.jar |- application.yml
將打好的jar包放在一個目錄下,比如叫做 hello的文件夾,然後再該文件夾下新建一個名為application.yml的文件,其中指定port為8088
,訪問路徑為/boot ,然後命令行直接啟動項目。java -jar a.jar
瀏覽器通過 localhost:8088/boot/hello 可以正常訪問,表示同級目錄下的配置文件生效了。 -
jar包內部的application-{profile}.properties或application.yml(帶spring.profile)配置文件
-
jar包外部的application.properties或application.yml(不帶spring.profile)配置文件
-
jar包外部的application.properties或application.yml(不帶spring.profile)配置文件
-
jar包內部的application.properties或application.yml(不帶spring.profile)配置文件
-
@Configuration註解類上的propertySource
-
通過SpringApplication.setDefaultProperties指定的預設屬性。
1.2 springboot內部載入順序
- 配置文件可以放在下麵四個地方(優先順序依次)
file:./config
:項目根目錄中config下file:./
:項目根目錄下classpath:./config
:項目的resources目錄中config下classpath:./
:項目的resources目錄下
當使用的項目是module級別的時候,必須使用級別是project級別才能掃描到
file:
下麵的文件
- 同目錄下
.properties
的優先順序比.yml
高, - 如果同一個配置屬性,多個文件都配置了,預設使用第一次讀取到的,後續不覆蓋
- 高優先順序會覆蓋低優先順序
1.3 改變預設的配置文件位置
**項目打包好以後,我們可以使用命令行參數的形式,啟動項目的時候來指定配置文件的新位置;指定預設載入的這些配置文件共同起作用形成互補配置
**
在 G盤目錄下,創建一個application.properties文件(yml也可以),定義埠為8085
打包項目,啟動命令行:
java -jar spring-boot-02-config-02.0.0.1-SNAPSHOT.jar --spring.config.location=G:/application.properties
回車運行。
瀏覽器訪問: http:localhost:8005/boot02/hello ,顯然外部指定的配置文件生效了,並且與之前的主配置文件形成了互補配置
1.4 使用profile配置和載入配置文件
1.4.1 使用.properties
文件
假如有開發、測試、生產三個不同的環境,需要定義三個不同環境下的配置
application.properties
applicaiton-dev.properties
applictiong-test.properties
applicaiton-prod.properties
在application.properties
文件中指定當前使用的環境:
server.port=8001
# 激活哪個配置文件
spring.profiles.active=dev
#spring.profiles.active=dev,prod,test
spring.profiles.include=prod
1.4.2 使用.yml
文件
因為在yml文件中,---
表示文檔分隔符,每個文檔獨立,所以此時只需要一個.yml
文件
spring:
profiles:
active: prod
---
spring:
profiles: dev
server: 8080
---
spring:
profiles: test
server: 8081
---
spring.profiles: prod
spring.profiles.include:
- proddb
- prodmq
server: 8082
---
spring:
profiles: proddb
db:
name: mysql
---
spring:
profiles: prodmq
mq:
address: localhost
此時讀取的就是prod的配置,prod包含proddb,prodmq,此時可以讀取proddb,prodmq下的配置
也可以同時激活三個配置spring.profiles.active: prod,proddb,prodmq
1.4.3 使用Java中的@Profile
註解
@Profile
註解只能配合@Configuration
和@Component
使用
@Configuration
@Profile("prod")
public class ProductionConfiguration {
// ...
}
1.5 讀取自定義配置文件
1.5.1 利用 @PropertiesSource
註解來實現
@PropertiesSource 可以用來載入指定的配置文件,預設只能載入 *.properties
文件, 不能載入 yml
等文件
相關屬性
- value: 指明載入配置文件的路徑
- ignoreResourceNotFound:指定的配置文件不存在是否報錯,預設是false。當設置為 true 時,若該文件不存在,程式不會報錯。實際項目開發中,最好設置
ignoreResourceNotFound 為 false。 - encoding:指定讀取屬性文件所使用的編碼,我們通常使用的是UTF-8。
示例
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Configuration
@PropertySource(value = {"classpath:common.properties"}, ignoreResourceNotFound = false, encoding = "UTF-8")
@ConfigurationProperties(prefix = "author")// 這個註解的作用是指明配置文件中需要註入信息的首碼
public class Author {
private Stirng name;
private String job;
private String sex;
}
當需要用 yml
作為配置文件時此時我們可以通過實現PropertySourceFactory介面,重寫createPropertySource方法,就能實現用@PropertySource也能載入yaml等類型文件。
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.core.io.support.PropertySourceFactory;
import org.springframework.util.StringUtils;
import java.io.FileNotFoundException;
import java.util.Properties;
public class YamlPropertiesSourceFactory 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) {
Throwable cause = e.getCause();
if (cause instanceof FileNotFoundException) {
throw (FileNotFoundException) cause;
}
throw e;
}
}
}
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Configuration
// 指明上面寫好的工廠類
@PropertySource(factory = YamlPropertySourceFactory.class, value = {"classpath:user.yml"},
ignoreResourceNotFound = false, encoding = "UTF-8")
@ConfigurationProperties(prefix = "author")// 這個註解的作用是指明配置文件中需要註入信息的首碼
public class Author {
private Stirng name;
private String job;
private String sex;
}
1.5.2 使用 EnvironmentPostProcessor
載入自定義配置文件
實現流程
- 實現EnvironmentPostProcessor介面,重寫postProcessEnvironment方法
public class MyEnvironmentPostProcessor implements EnvironmentPostProcessor {
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
String[] profiles = {"config/test.properties", "config/custom.properties", "config/blog.yml"};
for (String profile : profiles) {
Resource resource = new ClassPathResource(profile);
environment.getPropertySources().addLast(loadProfiles(resource));
}
}
private PropertySource<?> loadProfiles(Resource resource) {
if (!resource.exists()) {
throw new IllegalArgumentException("資源不存在");
}
if (resource.getFilename().endsWith("yml")) {
return loadYaml(resource);
} else {
return loadProperty(resource);
}
}
private PropertySource loadProperty(Resource resource) {
try {
Properties properties = new Properties();
properties.load(resource.getInputStream());
return new PropertiesPropertySource(resource.getFilename(), properties);
} catch (Exception e) {
throw new IllegalStateException("載入Property配置文件失敗", e);
}
}
private PropertySource loadYaml(Resource resource) {
try {
YamlPropertiesFactoryBean factoryBean = new YamlPropertiesFactoryBean();
factoryBean.setResources(resource);
Properties properties = factoryBean.getObject();
return new PropertiesPropertySource(resource.getFilename(), properties);
} catch (Exception e) {
throw new IllegalStateException("載入Yaml配置文件失敗", e);
}
}
}
- 在META-INF下創建spring.factories
# spring.factories 文件內容如下:
# 啟用自定義環境處理類
org.springframework.boot.env.EnvironmentPostProcessor=com.zhangyu.config.MyEnvironmentPostProcessor
1.6 SpringBoot使用通配符載入配置文件
還可以使用通配符載入自定義配置文件,貌似是spring的實現方式
@Configuration
public class PropertyConfig {
@Bean
public PropertySourcesPlaceholderConfigurer getPropertySourcesPlaceholderConfigurer() throws IOException {
PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
configurer.setLocations(new PathMatchingResourcePatternResolver().getResources("classpath:properties/*.properties"));
return configurer;
}
}
classpath*:
和classpath:
的區別是
classpath:
: 只會到你的class路徑中查找找文件。
classpath*:
: 不僅包含class路徑,還包括jar文件中(class路徑)進行查找。