您好,登錄后才能下訂單哦!
這篇文章主要介紹了SpringBoot外部化如何配置的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇SpringBoot外部化如何配置文章都會有所收獲,下面我們一起來看看吧。
Spring Boot可以讓你將配置外部化,這樣你就可以在不同的環境中使用相同的應用程序代碼。 你可以使用各種外部配置源,包括Java properties 文件、YAML文件、環境變量和命令行參數。
屬性值可以通過使用 @Value 注解直接注入你的Bean,也可以通過Spring 的 Environment 訪問,或者通過 @ConfigurationProperties 綁定到對象。同時 Spring Boot 也提供了一種非常特殊的 PropertyOrder,來允許用戶可以在適當的場景下覆蓋某些屬性值,該順序旨在允許合理地覆蓋值。
按以下順序優先級從低到高, 后者的屬性值覆蓋前者 ,所有的配置會形成互補配置:
默認屬性(使用 SpringApplication.setDefaultProperties 指定)
@Configuration
類上的@PropertySource
注解引入的配置屬性
請注意,這樣的屬性源直到ApplicationContext
被刷新時才會被添加到環境中。這對于配置某些屬性來說已經太晚了,比如logging.*
和spring.main.*
,它們在刷新開始前就已經被讀取了。
配置數據(例如application.properties文件)
對于random.*
形式的屬性,優先從RandomValuePropertySource
獲取(指優先于后者)
OS environment variables((操作系統環境變量)
Java System properties(Java 系統屬性System.getProperties()
)
JNDI 屬性
ServletContext 的 初始化參數
ServletConfig 的 初始化參數
SPRING_APPLICATION_JSON 屬性
命令行參數
test 模塊下的 properties 屬性
test 模塊下 @TestPropertySource 注解引入的配置文件
啟用 devtools 時 $HOME/.config/spring-boot 路徑下的配置
配置數據文件按以下加載順序考慮:
打包在 jar 中的應用程序屬性(application.properties 和 YAML)
打包在 jar 中的特定配置文件的應用程序屬性(application-{profile}.properties 和 YAML)
打包 jar 之外的應用程序屬性(application.properties 和 YAML)
打包 jar 之外的特定配置文件的應用程序屬性(application-{profile}.properties 和 YAML)
XML資源
Properties資源
YAML資源
Profile 本質上代表一種用于組織配置信息的維度,在不同場景下可以代表不同的含義。例如,如果 Profile 代表的是一種狀態,我們可以使用 open、halfopen、close 等值來分別代表全開、半開和關閉等。再比如系統需要設置一系列的模板,每個模板中保存著一系列配置項。
配置命名規則:
/{application}.yml /{application}-{profile}.yml /{label}/{application}-{profile}.yml /{application}-{profile}.properties /{label}/{application}-{profile}.properties
Spring Boot 啟動時,會自動加載 JAR 包內部及 JAR 包所在目錄指定位置的配置文件(Properties 文件、YAML 文件)。列表按優先級排序(較低項目的值覆蓋較早項目的值)
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 中的應用程序屬性(application.properties 和 YAML)。
打包 jar 之外的應用程序屬性(application.properties 和 YAML)
打包在 jar 中的特定于配置文件的應用程序屬性(application-{profile}.properties 和 YAML)
打包 jar 之外的特定于配置文件的應用程序屬性(application-{profile}.properties 和 YAML)
注意:在之前的版本中,JAR 包外部的application.properties
配置文件不會覆蓋 JAR 包里面的基于 "profile" 的application-{profile}.properties
配置文件。
2.4.0
以后版本,默認情況的搜索順序如下:保證了 JAR 包外部的應用程序參數應優先于 JAR 包內部的特定激活的配置參數
打包在 jar 中的應用程序屬性(application.properties 和 YAML)。
打包在 jar 中的特定于配置文件的應用程序屬性(application-{profile}.properties 和 YAML)
打包 jar 之外的應用程序屬性(application.properties 和 YAML)
打包 jar 之外的特定于配置文件的應用程序屬性(application-{profile}.properties 和 YAML)
注意:同一位置下,Properties 文件優先級高于 YAML 文件 , 如果Spring Boot在優先級更高的位置找到了配置,那么它就會無視優先級低的配置。
從 Spring Boot 2.4 開始,加載 Properties 和 YAML 文件時候會遵循, 在文檔中聲明排序靠前的屬性將被靠后的屬性覆蓋 。
命令行激活: --spring.profiles.active=prod
spring: profiles: active: dev #激活開發環境配置
配置文件激活如上,只需要在application.yml或者properties文件中配置即可
注意:在application.yml或者properties文件存在的情況下,不管激活的是prod還是dev,還是會讀取默認的配置文件,只不過指定的配置文件會覆蓋默認配置文件中的屬性
可以使用spring.config.import
屬性從其他地方導入更多的配置數據,比如spring.config.import=my.yaml
。它會將 my.yaml 文件作為臨時文件放在當前配置文件之后處理,因此其屬性具有更高的優先級
在運行Jar
包的命令中加入這個參數就可以指定Jar
包以外的配置文件的位置了,也可以在application的配置文件中配置該屬性
$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
這個參數就是指定外部application.yml
配置文件位置的參數,它支持classpath
和file
路徑
java -jar myproject.jar --spring.config.name=myproject
如果您不喜歡application.properties
作為配置文件名,您可以通過指定spring.config.name
環境屬性來切換到另一個文件名
對于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 來構建應用程序,那么可以按如下所示的配置項來動態獲取與系統構建過程相關的信息:
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
文件后,在開發人員的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
目錄下創建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 數組中包含的JSON對象可以包含下表中描述的屬性。
Name | 類型 | 目的 |
---|---|---|
name | String | 屬性的全名。 名稱采用小寫的句號分隔形式(例如,server.address)。 這個屬性是強制性的。 |
type | String | 該屬性的數據類型的完整簽名(例如,java.lang.String),但也有完整的通用類型(例如 java.util.Map<java.lang.String,com.example.MyEnum>)。 您可以使用此屬性來指導用戶可以輸入的值的類型。 為了保持一致性,基元的類型是通過使用其包裝類型來指定的(例如,boolean 變成 java.lang.Boolean)。 如果該類型不知道,可以省略。 |
description | String | 可以顯示給用戶的該property的簡短描述。 如果沒有描述,可以省略。 描述中的最后一行應以句號(.)結束。 |
sourceType | String | 貢獻此屬性的來源的類名。 例如,如果該屬性來自于一個用 @ConfigurationProperties 注解的類,該屬性將包含該類的完全限定名稱。 如果源類型未知,可以省略。 |
defaultValue | Object | 默認值,如果沒有指定該屬性,則使用該值。 如果該屬性的類型是一個數組,它可以是一個數組的值。 如果默認值是未知的,它可以被省略。 |
deprecation | Deprecation | 指定該屬性是否被廢棄。 如果該字段沒有被廢棄,或者不知道該信息,可以省略。 下表提供了關于 deprecation 屬性的更多細節。 |
包含在 hints 數組中的JSON對象可以包含下表中的屬性。
Name | 類型 | 目的 |
---|---|---|
name | String | 此提示所指向的屬性的全名。 名稱采用小寫的句號分隔形式(如 spring.mvc.servlet.path)。 這個屬性是強制性的。 |
values | ValueHint[] | 由 ValueHint 對象定義的有效值的列表(在下表中描述)。 每個條目都定義了值,并且可以有一個description。 |
每個 hint 元素的 values 屬性中包含的JSON對象可以包含下表中描述的屬性。
Name | 類型 | 目的 |
---|---|---|
value | Object | 提示所指的元素的一個有效值。 如果該屬性的類型是一個數組,它也可以是一個數組的值。 這個屬性是強制性的。 |
description | String | 可以顯示給用戶的價值的簡短描述。 如果沒有描述,可以省略。 描述中的最后一行應以句號(.)結束。 |
參考:http://www.mlszssj.com/article/191629.htm
啟動Spring Boot項目時傳遞參數,有三種參數形式:
選項參數,基本格式為--optName[=optValue]
(--
為連續兩個減號)
--foo --foo=bar --foo="bar then baz" --foo=bar,baz,biz
非選項參數
java -jar xxx.jar abc def
系統參數
java -jar -Dserver.port=8081 xxx.jar
相當于 SpringBoot 基于 Java 命令行參數中的非選項參數自定義了選項參數的規則,具體可以看解析器SimpleCommandLineArgsParser
,它里面調用其parse
方法對參數進行解析
class SimpleCommandLineArgsParser { public CommandLineArgs parse(String... args) { CommandLineArgs commandLineArgs = new CommandLineArgs(); for (String arg : args) { // --開頭的選參數解析 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; } }
如果您需要訪問傳遞給應用程序的參數SpringApplication.run(…)
,您可以注入一個ApplicationArguments
。該ApplicationArguments
接口提供對原始String[]
參數以及選項參數和非選項參數的訪問,如以下示例所示:
@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"] } }
另外,選項參數,也可以直接通過@Value
在類中獲取
系統參數可以通過java.lang.System提供的方法獲取
關于參數值區別,重點看選項參數和系統參數。通過上面的示例我們已經發現使用選項參數時,參數在命令中是位于xxx.jar
之后傳遞的,而系統參數是緊隨java -jar
之后。
如果不按照該順序進行執行,比如使用如下方式使用選項參數:
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.
如果將系統參數放在jar包后面,問題會更嚴重,會出現可以正常啟動,但參數無法生效。這個錯誤是最坑的,所以一定謹記:通過-D傳遞系統參數時,務必放置在待執行的jar包之前。
處理@PropertySource注解從ConfigurationClassParser#processPropertySource方法進
Spring中@PropertySource默認不支持YAML格式的解析,但是SpringBoot的配置文件卻可以解析YAML,這說明SpringBoot中已經實現了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的默認實現是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,所以我們可以通過實現PropertySourceFactory接口,然后用@PropertySource的factory屬性來實現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被創建之前觸發的,所以我們不能將這些事件的監聽器注冊為@Bean。
因為這個時候應用上下文還沒有被創建,也就是說監聽器也還沒有被初始化,這個先后順序不對,會導致這些事件的監聽器不會被觸發
但可以使用SpringApplication.addListeners(...)
方法或SpringApplicationBuilder.listeners(...)
方法注冊它們。
如果您希望這些偵聽器自動注冊的話,可以通過新建一個META-INF/spring.factories
文件,添加類似以下內容,SpringBoot會自動幫你注冊。
org.springframework.context.ApplicationListener=com.example.project.MyListener
應用程序運行時,應用程序事件按以下順序發送:
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外部化如何配置”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“SpringBoot外部化如何配置”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。