Spring Boot對于如何使用Spring構(gòu)建應(yīng)用程序有一個(gè)看法:例如它具有常規(guī)配置文件的常規(guī)位置淀衣,以及用于常見管理和監(jiān)視任務(wù)的端點(diǎn)。Spring Cloud建立在此之上零截,并添加了一些可能系統(tǒng)中所有組件將使用或偶爾需要的功能。
引導(dǎo)應(yīng)用程序上下文
一個(gè)Spring Cloud應(yīng)用程序通過創(chuàng)建一個(gè)“引導(dǎo)”上下文來進(jìn)行操作,這個(gè)上下文是主應(yīng)用程序的父上下文母截。開箱即用爽柒,負(fù)責(zé)從外部源加載配置屬性吴菠,還解密本地外部配置文件中的屬性。這兩個(gè)上下文共享一個(gè)Environment浩村,這是任何Spring應(yīng)用程序的外部屬性的來源做葵。Bootstrap屬性的優(yōu)先級高,因此默認(rèn)情況下不能被本地配置覆蓋心墅。
引導(dǎo)上下文使用與主應(yīng)用程序上下文不同的外部配置約定酿矢,因此使用bootstrap.ymlapplication.yml(或.properties)代替引導(dǎo)和主上下文的外部配置榨乎。例:
bootstrap.yml
spring:
? application:
? ? name: foo
? cloud:
? ? config:
? ? ? uri: ${SPRING_CONFIG_URI:http://localhost:8888}
如果您的應(yīng)用程序需要服務(wù)器上的特定于應(yīng)用程序的配置,那么設(shè)置spring.application.name(在bootstrap.yml或application.yml)中是個(gè)好主意瘫筐。
您可以通過設(shè)置spring.cloud.bootstrap.enabled=false(例如在系統(tǒng)屬性中)來完全禁用引導(dǎo)過程蜜暑。
應(yīng)用程序上下文層次結(jié)構(gòu)
如果您從SpringApplication或SpringApplicationBuilder構(gòu)建應(yīng)用程序上下文,則將Bootstrap上下文添加為該上下文的父級策肝。這是一個(gè)Spring的功能肛捍,即子上下文從其父進(jìn)程繼承屬性源和配置文件,因此與不使用Spring Cloud Config構(gòu)建相同上下文相比之众,“主”應(yīng)用程序上下文將包含其他屬性源拙毫。額外的財(cái)產(chǎn)來源是:
“bootstrap”:如果在Bootstrap上下文中找到任何PropertySourceLocators,則可選CompositePropertySource顯示為高優(yōu)先級棺禾,并且具有非空屬性缀蹄。一個(gè)例子是來自Spring Cloud Config服務(wù)器的屬性。有關(guān)如何自定義此屬性源的內(nèi)容的說明帘睦,請參閱
下文袍患。
“applicationConfig:[classpath:bootstrap.yml]”(如果Spring配置文件處于活動(dòng)狀態(tài),則為朋友)竣付。如果您有一個(gè)bootstrap.yml(或?qū)傩裕┕钛樱敲催@些屬性用于配置引導(dǎo)上下文,然后在父進(jìn)程設(shè)置時(shí)將它們添加到子上下文中古胆。它們的優(yōu)先級低于application.yml(或?qū)傩裕┮约白鳛閯?chuàng)建Spring Boot應(yīng)用程序的過程的正常部分添加到子級的任何其他屬性源肆良。有關(guān)如何自定義這些屬性源的內(nèi)容的說明,請參閱下文逸绎。
由于屬性源的排序規(guī)則惹恃,“引導(dǎo)”條目優(yōu)先,但請注意棺牧,這些條目不包含來自bootstrap.yml的任何數(shù)據(jù)巫糙,它具有非常低的優(yōu)先級,但可用于設(shè)置默認(rèn)值颊乘。
您可以通過簡單地設(shè)置您創(chuàng)建的任何ApplicationContext的父上下文來擴(kuò)展上下文層次結(jié)構(gòu)参淹,例如使用自己的界面,或使用SpringApplicationBuilder方便方法(parent()乏悄,child()和sibling())浙值。引導(dǎo)環(huán)境將是您創(chuàng)建自己的最高級祖先的父級。層次結(jié)構(gòu)中的每個(gè)上下文都將有自己的“引導(dǎo)”屬性源(可能為空)檩小,以避免無意中將值從父級升級到其后代开呐。層次結(jié)構(gòu)中的每個(gè)上下文(原則上)也可以具有不同的spring.application.name,因此如果存在配置服務(wù)器,則不同的遠(yuǎn)程屬性源筐付。普通的Spring應(yīng)用程序上下文行為規(guī)則適用于屬性解析:子環(huán)境中的屬性通過名稱和屬性源名稱覆蓋父項(xiàng)中的屬性(如果子級具有與父級名稱相同的屬性源卵惦,一個(gè)來自父母的孩子不包括在孩子中)。
請注意瓦戚,SpringApplicationBuilder允許您在整個(gè)層次結(jié)構(gòu)中共享Environment鸵荠,但這不是默認(rèn)值。因此伤极,兄弟情境尤其不需要具有相同的資料或財(cái)產(chǎn)來源,盡管它們與父母共享共同點(diǎn)姨伤。
改變引導(dǎo)位置Properties
可以使用spring.cloud.bootstrap.name(默認(rèn)“引導(dǎo)”)或spring.cloud.bootstrap.location(默認(rèn)為空)指定bootstrap.yml(或.properties)位置哨坪,例如在系統(tǒng)屬性中。這些屬性的行為類似于具有相同名稱的spring.config.*變體乍楚,實(shí)際上它們用于通過在其Environment中設(shè)置這些屬性來設(shè)置引導(dǎo)ApplicationContext当编。如果在正在構(gòu)建的上下文中有活動(dòng)的配置文件(來自spring.profiles.active或通過EnvironmentAPI)),則該配置文件中的屬性也將被加載徒溪,就像常規(guī)的Spring Boot應(yīng)用程序忿偷,例如來自bootstrap-development.properties的“開發(fā)”簡介。
覆蓋遠(yuǎn)程Properties的值
通過引導(dǎo)上下文添加到應(yīng)用程序的屬性源通常是“遠(yuǎn)程”(例如從配置服務(wù)器)臊泌,并且默認(rèn)情況下鲤桥,不能在本地覆蓋,除了在命令行上渠概。如果要允許您的應(yīng)用程序使用自己的系統(tǒng)屬性或配置文件覆蓋遠(yuǎn)程屬性茶凳,則遠(yuǎn)程屬性源必須通過設(shè)置spring.cloud.config.allowOverride=true(在本地設(shè)置本身不起作用)授予權(quán)限。一旦設(shè)置了該標(biāo)志播揪,就會(huì)有一些更精細(xì)的設(shè)置來控制遠(yuǎn)程屬性與系統(tǒng)屬性和應(yīng)用程序本地配置的位置:spring.cloud.config.overrideNone=true覆蓋任何本地屬性源贮喧,spring.cloud.config.overrideSystemProperties=false如果只有系統(tǒng)屬性和env var應(yīng)該覆蓋遠(yuǎn)程設(shè)置,而不是本地配置文件猪狈。
自定義引導(dǎo)配置
可以通過在org.springframework.cloud.bootstrap.BootstrapConfiguration鍵下添加條目/META-INF/spring.factories來訓(xùn)練引導(dǎo)上下文來執(zhí)行任何您喜歡的操作箱沦。這是用于創(chuàng)建上下文的Spring@Configuration類的逗號(hào)分隔列表。您可以在此處創(chuàng)建要用于自動(dòng)裝配的主應(yīng)用程序上下文的任何bean雇庙,并且還有ApplicationContextInitializer類型的@Beans的特殊合同谓形。如果要控制啟動(dòng)順序(默認(rèn)順序?yàn)椤白詈蟆保梢允褂聾Order標(biāo)記類状共。
警告添加自定義BootstrapConfiguration時(shí)套耕,請注意,您添加的類不是錯(cuò)誤的@ComponentScanned到您的“主”應(yīng)用程序上下文中峡继,可能不需要它們冯袍。對于您的@ComponentScan或@SpringBootApplication注釋配置類尚未涵蓋的啟動(dòng)配置類,請使用單獨(dú)的包名稱。
引導(dǎo)過程通過將初始化器注入主SpringApplication實(shí)例(即正常的Spring Boot啟動(dòng)順序康愤,無論是作為獨(dú)立應(yīng)用程序運(yùn)行還是部署在應(yīng)用程序服務(wù)器中)結(jié)束儡循。首先,從spring.factories中找到的類創(chuàng)建引導(dǎo)上下文征冷,然后在ApplicationContextInitializer類型的所有@Beans添加到主SpringApplication開始之前择膝。
自定義引導(dǎo)屬性源
引導(dǎo)過程添加的外部配置的默認(rèn)屬性源是Config Server,但您可以通過將PropertySourceLocator類型的bean添加到引導(dǎo)上下文(通過spring.factories)添加其他源检激。您可以使用此方法從其他服務(wù)器或數(shù)據(jù)庫中插入其他屬性肴捉。
作為一個(gè)例子,請考慮以下微不足道的自定義定位器:
@Configuration
public class CustomPropertySourceLocator implements PropertySourceLocator {
? ? @Override
? ? public PropertySource<?> locate(Environment environment) {
? ? ? ? return new MapPropertySource("customProperty",
? ? ? ? ? ? ? ? Collections.<String, Object>singletonMap("property.from.sample.custom.source", "worked as intended"));
? ? }
}
傳入的Environment是要?jiǎng)?chuàng)建的ApplicationContext的Environment叔收,即為我們提供額外的屬性來源的齿穗。它將已經(jīng)具有正常的Spring Boot提供的資源來源,因此您可以使用它們來定位特定于此Environment的屬性源(例如通過將其綁定在spring.application.name上饺律,如在默認(rèn)情況下所做的那樣Config Server屬性源定位器)窃页。
如果你在這個(gè)類中創(chuàng)建一個(gè)jar,然后添加一個(gè)META-INF/spring.factories包含:
org.springframework.cloud.bootstrap.BootstrapConfiguration=sample.custom.CustomPropertySourceLocator
那么“customProperty”PropertySource將顯示在其類路徑中包含該jar的任何應(yīng)用程序中复濒。
環(huán)境變化
應(yīng)用程序?qū)⑹章燛nvironmentChangeEvent脖卖,并以幾種標(biāo)準(zhǔn)方式進(jìn)行更改(用戶可以以常規(guī)方式添加ApplicationListeners附加ApplicationListeners)。當(dāng)觀察到EnvironmentChangeEvent時(shí)巧颈,它將有一個(gè)已更改的鍵值列表畦木,應(yīng)用程序?qū)⑹褂靡韵聝?nèi)容:
重新綁定上下文中的任何@ConfigurationPropertiesbean
為logging.level.*中的任何屬性設(shè)置記錄器級別
請注意,配置客戶端不會(huì)通過默認(rèn)輪詢查找Environment中的更改砸泛,通常我們不建議檢測更改的方法(盡管可以使用@Scheduled注釋進(jìn)行設(shè)置)馋劈。如果您有一個(gè)擴(kuò)展的客戶端應(yīng)用程序,那么最好將EnvironmentChangeEvent廣播到所有實(shí)例晾嘶,而不是讓它們輪詢更改(例如使用Spring Cloud總線)妓雾。
EnvironmentChangeEvent涵蓋了大量的刷新用例,只要您真的可以更改Environment并發(fā)布事件(這些API是公開的垒迂,部分內(nèi)核為Spring)械姻。您可以通過訪問/configprops端點(diǎn)(普通Spring Boot執(zhí)行器功能)來驗(yàn)證更改是否綁定到@ConfigurationPropertiesbean。例如机断,DataSource可以在運(yùn)行時(shí)更改其maxPoolSize(由Spring Boot創(chuàng)建的默認(rèn)DataSource是一個(gè)@ConfigurationPropertiesbean)楷拳,并且動(dòng)態(tài)增加容量。重新綁定@ConfigurationProperties不會(huì)覆蓋另一大類用例吏奸,您需要更多的控制刷新欢揖,并且您需要更改在整個(gè)ApplicationContext上是原子的。為了解決這些擔(dān)憂奋蔚,我們有@RefreshScope她混。
刷新范圍
當(dāng)配置更改時(shí)烈钞,標(biāo)有@RefreshScope的Spring@Bean將得到特殊處理。這解決了狀態(tài)bean在初始化時(shí)只注入配置的問題坤按。例如毯欣,如果通過Environment更改數(shù)據(jù)庫URL時(shí)DataSource有開放連接,那么我們可能希望這些連接的持有人能夠完成他們正在做的工作臭脓。然后下一次有人從游泳池借用一個(gè)連接酗钞,他得到一個(gè)新的URL。
刷新范圍bean是在使用時(shí)初始化的懶惰代理(即當(dāng)調(diào)用一個(gè)方法時(shí))来累,并且作用域作為初始值的緩存砚作。要強(qiáng)制bean重新初始化下一個(gè)方法調(diào)用,您只需要使其緩存條目無效嘹锁。
RefreshScope是上下文中的一個(gè)bean偎巢,它有一個(gè)公共方法refreshAll()來清除目標(biāo)緩存中的范圍內(nèi)的所有bean。還有一個(gè)refresh(String)方法可以按名稱刷新單個(gè)bean兼耀。此功能在/refresh端點(diǎn)(通過HTTP或JMX)中公開。
注意@RefreshScope(技術(shù)上)在@Configuration類上工作求冷,但可能會(huì)導(dǎo)致令人驚訝的行為:例如瘤运,這并不意味著該類中定義的所有@Beans本身都是@RefreshScope。具體來說匠题,任何取決于這些bean的東西都不能依賴它們在刷新啟動(dòng)時(shí)被更新拯坟,除非它本身在@RefreshScope(在其中將重新刷新并重新注入其依賴關(guān)系),那么它們將從刷新的@Configuration)重新初始化韭山。
加密和解密
Spring Cloud具有一個(gè)用于在本地解密屬性值的Environment預(yù)處理器郁季。它遵循與Config Server相同的規(guī)則,并通過encrypt.*具有相同的外部配置钱磅。因此梦裂,您可以使用{cipher}*格式的加密值,只要有一個(gè)有效的密鑰盖淡,那么在主應(yīng)用程序上下文獲取Environment之前年柠,它們將被解密。要在應(yīng)用程序中使用加密功能褪迟,您需要在您的類路徑中包含Spring安全性RSA(Maven協(xié)調(diào)“org.springframework.security:spring-security-rsa”)冗恨,并且還需要全面強(qiáng)大的JCE擴(kuò)展你的JVM
如果由于“非法密鑰大小”而導(dǎo)致異常,并且您正在使用Sun的JDK味赃,則需要安裝Java加密擴(kuò)展(JCE)無限強(qiáng)度管理策略文件掀抹。有關(guān)詳細(xì)信息,請參閱以下鏈接:
將文件解壓縮到JDK / jre / lib / security文件夾(無論您使用的是哪個(gè)版本的JRE / JDK x64 / x86)心俗。
端點(diǎn)
對于Spring Boot執(zhí)行器應(yīng)用程序傲武,還有一些額外的管理端點(diǎn):
POST到/env以更新Environment并重新綁定@ConfigurationProperties和日志級別
/refresh重新加載引導(dǎo)帶上下文并刷新@RefreshScopebean
/restart關(guān)閉ApplicationContext并重新啟動(dòng)(默認(rèn)情況下禁用)
/pause和/resume調(diào)用Lifecycle方法(stop()和start()ApplicationContext)