springboot如何使用自定義配置文件

  從前邊《springboot竟然有5種默認的加載路徑,你未必都知道》我們知道,springboot會默認加載application.properties/application.yml配置文件,且會從下面5個默認的路徑下加載,其優先級依次升高,後面的會覆蓋前邊的配置。我們平時使用resources/application.properties其實優先級是最低。

// Note the order is from least to most specific (last one wins)
private static final String DEFAULT_SEARCH_LOCATIONS = "classpath:/,classpath:/config/,file:./,file:./config/*/,file:./config/";

  既然知道了springboot會從默認的路徑加載默認的配置文件application.properties/application.yml,那麼必然可以自定義。

一、如何自定義

  這裏分爲兩部分,一個是自定義配置文件,一個是自定義配置文件的路徑。祕密就藏在上篇文章提到的一個類中:ConfigFileApplicationListener,再來看下該類的註釋,下面僅貼出部分,

 * <p>
 * The 'spring.config.name' property can be used to specify an alternative name to load
 * and the 'spring.config.location' property can be used to specify alternative search
 * locations or specific files.
 * <p>

這段註釋是什麼意思吶,大體意思是“通過指定spring.config.name屬性來替代默認的配置文件名稱,通過指定spring.config.location屬性來替代默認配置文件的加載路徑”。再來看ConfigFileApplicationListener類中的屬性,

/**
* The "config name" property name.
 */
public static final String CONFIG_NAME_PROPERTY = "spring.config.name";

/**
* The "config location" property name.
*/
public static final String CONFIG_LOCATION_PROPERTY = "spring.config.location";

可以看到在該類中定義了兩個常量來接收“spring.config.name”和“spring.config.location”屬性的值。 

二、如何使用

  上面已經瞭解到可以通過配置“spring.config.name”和“spring.config.location”屬性值來自定義默認配置文件和默認配置文件的加載路徑。現在就來試試,使用properties文件來演示,在resources文件夾下建myconfig/custom.properties,

現在,如果啓動服務肯定不會使用端口“9099”,因爲前邊說到springboot有自己的默認加載路徑及默認的配置文件名,現在自定義的文件是resources/myconfig/custome.properties,springboot不會加載到,前邊又說到springboot定義了“spring.config.name”和“spring.config.location”兩個屬性,現在就需要使用這兩個屬性指定自定義的配置文件。

2.1、從源碼中學習如何使用

要指定如何使用“spring.config.name”和“spring.config.location”兩個配置,還是得去源碼中尋找,前面說到這兩個屬性在ConfigFileApplicationListener類中,在該類中在下面的地方使用了這兩個屬性,

private Set<String> getSearchNames() {
           //使用CONFIG_NAME_PROPERTY常量也就是spring.config.name
			if (this.environment.containsProperty(CONFIG_NAME_PROPERTY)) {
				String property = this.environment.getProperty(CONFIG_NAME_PROPERTY);
				Set<String> names = asResolvedSet(property, null);
				names.forEach(this::assertValidConfigName);
				return names;
			}
			return asResolvedSet(ConfigFileApplicationListener.this.names, DEFAULT_NAMES);
		}

private Set<String> getSearchLocations() {
			Set<String> locations = getSearchLocations(CONFIG_ADDITIONAL_LOCATION_PROPERTY);
            //使用CONFIG_LOCATION_PROPERTY常量也就是spring.config.location
			if (this.environment.containsProperty(CONFIG_LOCATION_PROPERTY)) {
				locations.addAll(getSearchLocations(CONFIG_LOCATION_PROPERTY));
			}
			else {
				locations.addAll(
						asResolvedSet(ConfigFileApplicationListener.this.searchLocations, DEFAULT_SEARCH_LOCATIONS));
			}
			return locations;
		}

從上面的代碼中得出這樣一個規律都是調用this.environment 中的方法,那麼這個environment到底是什麼,如下

完全看不出來,這時候只有通過debug了,在ConfigFileApplicationListener類中打上斷點,看到environment是一個StandardServletEnvironment實例,

那就好辦了,找到該類即可,該類中有這樣的一個方法:customizePropertySources,直譯過來是“自定義屬性來源”,

@Override
	protected void customizePropertySources(MutablePropertySources propertySources) {
		propertySources.addLast(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME));
		propertySources.addLast(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
		if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {
			propertySources.addLast(new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME));
		}
		super.customizePropertySources(propertySources);
	}

從該類中可以看到向propertySources中新加了好幾個屬性,我們看下面這句,

super.customizePropertySources(propertySources);

調用的是父類的方法,父類方法如下,

@Override
	protected void customizePropertySources(MutablePropertySources propertySources) {
		propertySources.addLast(
				new PropertiesPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
		propertySources.addLast(
				new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
	}

看到又向propertySources中放入了兩個值,分別是下面兩個常量,

/** System environment property source name: {@value}. */
public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment";

/** JVM system properties property source name: {@value}. */
public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties";

根據註釋我們知道,

SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME  表示的是系統環境參數

SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME  表示的是JVM系統參數

也就是說springboot會從系統環境變量和JVM參數中讀取配置信息,結合前邊的分析,“spring.config.name”和“spring.config.location”會從系統環境變量和JVM參數中獲取。

2.2、配置系統環境變量和JVM參數

前邊已經從源碼中知道了“spring.config.name”和“spring.location”應該如何配置,現在看下配置效果。

2.2.1、配置JVM參數

配置JVM參數看下效果,配置如下,

-Dspring.config.name=custom
-Dspring.config.location=classpath:myconfig/

配置好的效果如下,

看下服務在哪個端口啓動,

服務在端口“9099”啓動,使用到了我們自定義的配置文件:resources/myconfig/custom.properties。

2.2.2、配置系統環境變量

配置的信息如下,

spring.config.name=custom
spring.config.location=classpath:myconfig/

配置好的效果,

測試結果,我就不再貼了,服務使用的我們自定義的配置文件。

讀到這裏不知道小夥伴們是否有個疑惑,JVM參數和系統環境變量有優先級嗎,當然是有的,咱們繼續。

2.3、優先級之爭

在resources下再建myconfig2/custom.properties文件,端口爲9098,

分別配置JVM參數和系統環境變量,

最後服務是在端口“9099”啓動,

由此我們可以得出結論,JVM參數的優先級大於系統環境變量

三、總結

  本文主要分享了在springboot中如何使用自定義的配置文件,主要有以下幾點

  1、定義自己的配置文件;

  2、使用“spring.config.name”、“spring.config.location”定義文件名稱、文件位置;

  3、可以在JVM參數、系統環境變量配置“spring.config.name”、“spring.config.location”;JVM參數的優先級大於系統環境變量;

 

不知道有沒有小夥伴還存在一個疑問,我是有疑問的,什麼是JVM參數?什麼是系統環境變量?後續咱們繼續分享。

推薦閱讀

springboot竟然有5種默認的加載路徑,你未必都知道

5分鐘快速搭建一個springboot的項目

springboot:讀取application.yml文件

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章