您好,登錄后才能下訂單哦!
這篇文章主要介紹了SpringBoot外部化如何配置的相關知識,內(nèi)容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇SpringBoot外部化如何配置文章都會有所收獲,下面我們一起來看看吧。
Spring Boot可以讓你將配置外部化,這樣你就可以在不同的環(huán)境中使用相同的應用程序代碼。 你可以使用各種外部配置源,包括Java properties 文件、YAML文件、環(huán)境變量和命令行參數(shù)。
屬性值可以通過使用 @Value 注解直接注入你的Bean,也可以通過Spring 的 Environment 訪問,或者通過 @ConfigurationProperties 綁定到對象。同時 Spring Boot 也提供了一種非常特殊的 PropertyOrder,來允許用戶可以在適當?shù)膱鼍跋赂采w某些屬性值,該順序旨在允許合理地覆蓋值。
按以下順序優(yōu)先級從低到高, 后者的屬性值覆蓋前者 ,所有的配置會形成互補配置:
默認屬性(使用 SpringApplication.setDefaultProperties 指定)
@Configuration
類上的@PropertySource
注解引入的配置屬性
請注意,這樣的屬性源直到ApplicationContext
被刷新時才會被添加到環(huán)境中。這對于配置某些屬性來說已經(jīng)太晚了,比如logging.*
和spring.main.*
,它們在刷新開始前就已經(jīng)被讀取了。
配置數(shù)據(jù)(例如application.properties文件)
對于random.*
形式的屬性,優(yōu)先從RandomValuePropertySource
獲?。ㄖ竷?yōu)先于后者)
OS environment variables((操作系統(tǒng)環(huán)境變量)
Java System properties(Java 系統(tǒng)屬性System.getProperties()
)
JNDI 屬性
ServletContext 的 初始化參數(shù)
ServletConfig 的 初始化參數(shù)
SPRING_APPLICATION_JSON 屬性
命令行參數(shù)
test 模塊下的 properties 屬性
test 模塊下 @TestPropertySource 注解引入的配置文件
啟用 devtools 時 $HOME/.config/spring-boot 路徑下的配置
配置數(shù)據(jù)文件按以下加載順序考慮:
打包在 jar 中的應用程序?qū)傩裕╝pplication.properties 和 YAML)
打包在 jar 中的特定配置文件的應用程序?qū)傩裕╝pplication-{profile}.properties 和 YAML)
打包 jar 之外的應用程序?qū)傩裕╝pplication.properties 和 YAML)
打包 jar 之外的特定配置文件的應用程序?qū)傩裕╝pplication-{profile}.properties 和 YAML)
XML資源
Properties資源
YAML資源
Profile 本質(zhì)上代表一種用于組織配置信息的維度,在不同場景下可以代表不同的含義。例如,如果 Profile 代表的是一種狀態(tài),我們可以使用 open、halfopen、close 等值來分別代表全開、半開和關閉等。再比如系統(tǒng)需要設置一系列的模板,每個模板中保存著一系列配置項。
配置命名規(guī)則:
/{application}.yml /{application}-{profile}.yml /{label}/{application}-{profile}.yml /{application}-{profile}.properties /{label}/{application}-{profile}.properties
Spring Boot 啟動時,會自動加載 JAR 包內(nèi)部及 JAR 包所在目錄指定位置的配置文件(Properties 文件、YAML 文件)。列表按優(yōu)先級排序(較低項目的值覆蓋較早項目的值)
classpath( –classpath )
classpath 根路徑
classpath 下的 /config 包
當前目錄( –file )
當前目錄下
當前目錄下的 config/ 子目錄
當前目錄下的 config/ 子目錄的直接子目錄
. project-sample ├── config │ ├── application.yml (4) │ └── src/main/resources | │ ├── application.yml (1) | │ └── config | | │ ├── application.yml (2) ├── application.yml (3)
啟動時加載配置文件順序:1 > 2 > 3 > 4
2.4.0
以前版本,默認情況的加載順序如下:
打包在 jar 中的應用程序?qū)傩裕╝pplication.properties 和 YAML)。
打包 jar 之外的應用程序?qū)傩裕╝pplication.properties 和 YAML)
打包在 jar 中的特定于配置文件的應用程序?qū)傩裕╝pplication-{profile}.properties 和 YAML)
打包 jar 之外的特定于配置文件的應用程序?qū)傩裕╝pplication-{profile}.properties 和 YAML)
注意:在之前的版本中,JAR 包外部的application.properties
配置文件不會覆蓋 JAR 包里面的基于 "profile" 的application-{profile}.properties
配置文件。
2.4.0
以后版本,默認情況的搜索順序如下:保證了 JAR 包外部的應用程序參數(shù)應優(yōu)先于 JAR 包內(nèi)部的特定激活的配置參數(shù)
打包在 jar 中的應用程序?qū)傩裕╝pplication.properties 和 YAML)。
打包在 jar 中的特定于配置文件的應用程序?qū)傩裕╝pplication-{profile}.properties 和 YAML)
打包 jar 之外的應用程序?qū)傩裕╝pplication.properties 和 YAML)
打包 jar 之外的特定于配置文件的應用程序?qū)傩裕╝pplication-{profile}.properties 和 YAML)
注意:同一位置下,Properties 文件優(yōu)先級高于 YAML 文件 , 如果Spring Boot在優(yōu)先級更高的位置找到了配置,那么它就會無視優(yōu)先級低的配置。
從 Spring Boot 2.4 開始,加載 Properties 和 YAML 文件時候會遵循, 在文檔中聲明排序靠前的屬性將被靠后的屬性覆蓋 。
命令行激活: --spring.profiles.active=prod
spring: profiles: active: dev #激活開發(fā)環(huán)境配置
配置文件激活如上,只需要在application.yml或者properties文件中配置即可
注意:在application.yml或者properties文件存在的情況下,不管激活的是prod還是dev,還是會讀取默認的配置文件,只不過指定的配置文件會覆蓋默認配置文件中的屬性
可以使用spring.config.import
屬性從其他地方導入更多的配置數(shù)據(jù),比如spring.config.import=my.yaml
。它會將 my.yaml 文件作為臨時文件放在當前配置文件之后處理,因此其屬性具有更高的優(yōu)先級
在運行Jar
包的命令中加入這個參數(shù)就可以指定Jar
包以外的配置文件的位置了,也可以在application的配置文件中配置該屬性
$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
這個參數(shù)就是指定外部application.yml
配置文件位置的參數(shù),它支持classpath
和file
路徑
java -jar myproject.jar --spring.config.name=myproject
如果您不喜歡application.properties
作為配置文件名,您可以通過指定spring.config.name
環(huán)境屬性來切換到另一個文件名
對于spring.config.location
、spring.config.additional-location
和spring.config.import
等屬性的路徑,添加optional:
前綴,則當對應文件不存在時應用仍可以正常啟動
比如spring.config.location=optional:file:/my.yaml
,當應用啟動加載文件 my.yaml 不存在時,不會拋出異常
例如,如果想要獲取當前應用程序的名稱并作為一個配置項進行管理,那么很簡單,我們直接通過 ${spring.application.name} 占位符:
myapplication.name : ${spring.application.name}
假設我們使用 Maven 來構建應用程序,那么可以按如下所示的配置項來動態(tài)獲取與系統(tǒng)構建過程相關的信息:
info: app: encoding: @project.build.sourceEncoding@ java: source: @java.version@ target: @java.version@ # 等同于下述效果 info: app: encoding: UTF-8 java: source: 1.8.0_31 target: 1.8.0_31
additional-spring-configuration-metadata.json
、spring-configuration-metadata.json
在springboot-starter官方項目或第三方starter項目中隨處可見,那它起的作用是什么?
配置additional-spring-configuration-metadata.json
文件后,在開發(fā)人員的IDE工具使用個人編寫的配置讀取很有效的在application.properties
或application.yml
文件下完成提示
在Maven中,該依賴關系應被聲明為可選的,如以下例子所示。
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
在resources/META-INF
目錄下創(chuàng)建additional-spring-configuration-metadata.json
,分類為 “groups” 或 “properties”,附加值提示分類為 "hints",如以下例子所示:
{ "groups": [ { "name": "server", "type": "org.springframework.boot.autoconfigure.web.ServerProperties", "sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties" }, { "name": "spring.jpa.hibernate", "type": "org.springframework.boot.autoconfigure.orm.jpa.JpaProperties$Hibernate", "sourceType": "org.springframework.boot.autoconfigure.orm.jpa.JpaProperties", "sourceMethod": "getHibernate()" } ... ], "properties": [ { "name": "server.port", "type": "java.lang.Integer", "sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties" }, { "name": "server.address", "type": "java.net.InetAddress", "sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties" }, { "name": "spring.jpa.hibernate.ddl-auto", "type": "java.lang.String", "description": "DDL mode. This is actually a shortcut for the "hibernate.hbm2ddl.auto" property.", "sourceType": "org.springframework.boot.autoconfigure.orm.jpa.JpaProperties$Hibernate" } ... ], "hints": [ { "name": "spring.jpa.hibernate.ddl-auto", "values": [ { "value": "none", "description": "Disable DDL handling." }, { "value": "validate", "description": "Validate the schema, make no changes to the database." }, { "value": "update", "description": "Update the schema if necessary." }, { "value": "create", "description": "Create the schema and destroy previous data." }, { "value": "create-drop", "description": "Create and then destroy the schema at the end of the session." } ] } ] }
properties 數(shù)組中包含的JSON對象可以包含下表中描述的屬性。
Name | 類型 | 目的 |
---|---|---|
name | String | 屬性的全名。 名稱采用小寫的句號分隔形式(例如,server.address)。 這個屬性是強制性的。 |
type | String | 該屬性的數(shù)據(jù)類型的完整簽名(例如,java.lang.String),但也有完整的通用類型(例如 java.util.Map<java.lang.String,com.example.MyEnum>)。 您可以使用此屬性來指導用戶可以輸入的值的類型。 為了保持一致性,基元的類型是通過使用其包裝類型來指定的(例如,boolean 變成 java.lang.Boolean)。 如果該類型不知道,可以省略。 |
description | String | 可以顯示給用戶的該property的簡短描述。 如果沒有描述,可以省略。 描述中的最后一行應以句號(.)結(jié)束。 |
sourceType | String | 貢獻此屬性的來源的類名。 例如,如果該屬性來自于一個用 @ConfigurationProperties 注解的類,該屬性將包含該類的完全限定名稱。 如果源類型未知,可以省略。 |
defaultValue | Object | 默認值,如果沒有指定該屬性,則使用該值。 如果該屬性的類型是一個數(shù)組,它可以是一個數(shù)組的值。 如果默認值是未知的,它可以被省略。 |
deprecation | Deprecation | 指定該屬性是否被廢棄。 如果該字段沒有被廢棄,或者不知道該信息,可以省略。 下表提供了關于 deprecation 屬性的更多細節(jié)。 |
包含在 hints 數(shù)組中的JSON對象可以包含下表中的屬性。
Name | 類型 | 目的 |
---|---|---|
name | String | 此提示所指向的屬性的全名。 名稱采用小寫的句號分隔形式(如 spring.mvc.servlet.path)。 這個屬性是強制性的。 |
values | ValueHint[] | 由 ValueHint 對象定義的有效值的列表(在下表中描述)。 每個條目都定義了值,并且可以有一個description。 |
每個 hint 元素的 values 屬性中包含的JSON對象可以包含下表中描述的屬性。
Name | 類型 | 目的 |
---|---|---|
value | Object | 提示所指的元素的一個有效值。 如果該屬性的類型是一個數(shù)組,它也可以是一個數(shù)組的值。 這個屬性是強制性的。 |
description | String | 可以顯示給用戶的價值的簡短描述。 如果沒有描述,可以省略。 描述中的最后一行應以句號(.)結(jié)束。 |
參考:http://www.kemok4.com/article/191629.htm
啟動Spring Boot項目時傳遞參數(shù),有三種參數(shù)形式:
選項參數(shù),基本格式為--optName[=optValue]
(--
為連續(xù)兩個減號)
--foo --foo=bar --foo="bar then baz" --foo=bar,baz,biz
非選項參數(shù)
java -jar xxx.jar abc def
系統(tǒng)參數(shù)
java -jar -Dserver.port=8081 xxx.jar
相當于 SpringBoot 基于 Java 命令行參數(shù)中的非選項參數(shù)自定義了選項參數(shù)的規(guī)則,具體可以看解析器SimpleCommandLineArgsParser
,它里面調(diào)用其parse
方法對參數(shù)進行解析
class SimpleCommandLineArgsParser { public CommandLineArgs parse(String... args) { CommandLineArgs commandLineArgs = new CommandLineArgs(); for (String arg : args) { // --開頭的選參數(shù)解析 if (arg.startsWith("--")) { // 獲得key=value或key值 String optionText = arg.substring(2, arg.length()); String optionName; String optionValue = null; // 如果是key=value格式則進行解析 if (optionText.contains("=")) { optionName = optionText.substring(0, optionText.indexOf('=')); optionValue = optionText.substring(optionText.indexOf('=')+1, optionText.length()); } else { // 如果是僅有key(--foo)則獲取其值 optionName = optionText; } // 如果optionName為空或者optionValue不為空但optionName為空則拋出異常 if (optionName.isEmpty() || (optionValue != null && optionValue.isEmpty())) { throw new IllegalArgumentException("Invalid argument syntax: " + arg); } // 封裝入CommandLineArgs commandLineArgs.addOptionArg(optionName, optionValue); } else { commandLineArgs.addNonOptionArg(arg); } } return commandLineArgs; } }
如果您需要訪問傳遞給應用程序的參數(shù)SpringApplication.run(…)
,您可以注入一個ApplicationArguments
。該ApplicationArguments
接口提供對原始String[]
參數(shù)以及選項參數(shù)和非選項參數(shù)的訪問,如以下示例所示:
@Component public class MyBean { @Autowired public MyBean(ApplicationArguments args) { boolean debug = args.containsOption("debug"); List<String> files = args.getNonOptionArgs(); // if run with "--debug logfile.txt" debug=true, files=["logfile.txt"] } }
另外,選項參數(shù),也可以直接通過@Value
在類中獲取
系統(tǒng)參數(shù)可以通過java.lang.System提供的方法獲取
關于參數(shù)值區(qū)別,重點看選項參數(shù)和系統(tǒng)參數(shù)。通過上面的示例我們已經(jīng)發(fā)現(xiàn)使用選項參數(shù)時,參數(shù)在命令中是位于xxx.jar
之后傳遞的,而系統(tǒng)參數(shù)是緊隨java -jar
之后。
如果不按照該順序進行執(zhí)行,比如使用如下方式使用選項參數(shù):
java -jar --server.port=8081 xxx.jar
則會拋出如下異常:
Unrecognized option: --server.port=8081 Error: Could not create the Java Virtual Machine. Error: A fatal exception has occurred. Program will exit.
如果將系統(tǒng)參數(shù)放在jar包后面,問題會更嚴重,會出現(xiàn)可以正常啟動,但參數(shù)無法生效。這個錯誤是最坑的,所以一定謹記:通過-D傳遞系統(tǒng)參數(shù)時,務必放置在待執(zhí)行的jar包之前。
處理@PropertySource注解從ConfigurationClassParser#processPropertySource方法進
Spring中@PropertySource默認不支持YAML格式的解析,但是SpringBoot的配置文件卻可以解析YAML,這說明SpringBoot中已經(jīng)實現(xiàn)了YAML文件的解析,我們只需要復用即可,我們可以看該注解源碼
/** * Specify a custom {@link PropertySourceFactory}, if any. * <p>By default, a default factory for standard resource files will be used. * @since 4.3 * @see org.springframework.core.io.support.DefaultPropertySourceFactory * @see org.springframework.core.io.support.ResourcePropertySource */ Class<? extends PropertySourceFactory> factory() default PropertySourceFactory.class;
PropertySourceFactory的默認實現(xiàn)是DefaultPropertySourceFactory
public class DefaultPropertySourceFactory implements PropertySourceFactory { @Override public PropertySource<?> createPropertySource(@Nullable String name, EncodedResource resource) throws IOException { return (name != null ? new ResourcePropertySource(name, resource) : new ResourcePropertySource(resource)); } }
ResourcePropertySource默認不支持YAML,所以我們可以通過實現(xiàn)PropertySourceFactory接口,然后用@PropertySource的factory屬性來實現(xiàn)YAML的解析
public class YamlPropertySourceFactory implements PropertySourceFactory { @Override public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException { YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean(); yamlPropertiesFactoryBean.setResources(resource.getResource()); Properties yamlProperties = yamlPropertiesFactoryBean.getObject(); return new PropertiesPropertySource(name, yamlProperties); } }
官方文檔中有說到:有些事件實際上是在ApplicationContext被創(chuàng)建之前觸發(fā)的,所以我們不能將這些事件的監(jiān)聽器注冊為@Bean。
因為這個時候應用上下文還沒有被創(chuàng)建,也就是說監(jiān)聽器也還沒有被初始化,這個先后順序不對,會導致這些事件的監(jiān)聽器不會被觸發(fā)
但可以使用SpringApplication.addListeners(...)
方法或SpringApplicationBuilder.listeners(...)
方法注冊它們。
如果您希望這些偵聽器自動注冊的話,可以通過新建一個META-INF/spring.factories
文件,添加類似以下內(nèi)容,SpringBoot會自動幫你注冊。
org.springframework.context.ApplicationListener=com.example.project.MyListener
應用程序運行時,應用程序事件按以下順序發(fā)送:
An ApplicationStartingEvent is sent at the start of a run but before any processing, except for the registration of listeners and initializers.
An ApplicationEnvironmentPreparedEvent is sent when the Environment to be used in the context is known but before the context is created.
An ApplicationContextInitializedEvent is sent when the ApplicationContext is prepared and ApplicationContextInitializers have been called but before any bean definitions are loaded.
An ApplicationPreparedEvent is sent just before the refresh is started but after bean definitions have been loaded.
An ApplicationStartedEvent is sent after the context has been refreshed but before any application and command-line runners have been called.
An AvailabilityChangeEvent is sent right after with LivenessState.CORRECT to indicate that the application is considered as live.
An ApplicationReadyEvent is sent after any application and command-line runners have been called.
An AvailabilityChangeEvent is sent right after with ReadinessState.ACCEPTING_TRAFFIC to indicate that the application is ready to service requests.
An ApplicationFailedEvent is sent if there is an exception on startup.
The above list only includes SpringApplicationEvents that are tied to a SpringApplication. In addition to these, the following events are also published after ApplicationPreparedEvent and before ApplicationStartedEvent:
A WebServerInitializedEvent is sent after the WebServer is ready. ServletWebServerInitializedEvent and ReactiveWebServerInitializedEvent are the servlet and reactive variants respectively.
A ContextRefreshedEvent is sent when an ApplicationContext is refreshed.
關于“SpringBoot外部化如何配置”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對“SpringBoot外部化如何配置”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業(yè)資訊頻道。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。