10.外化配置

  • Spring Boot允許外化(externalize)你的配置,這樣你能夠在不同的環(huán)境下使用相同的代碼。你可以使用properties文件,YAML文件,環(huán)境變量和命令行參數(shù)來(lái)外化配置。使用@Value注解,可以直接將屬性值注入到你的beans中,并通過(guò)Spring的Environment抽象或綁定到結(jié)構(gòu)化對(duì)象來(lái)訪問(wèn)。

  • Spring Boot使用一個(gè)非常特別的PropertySource次序來(lái)允許對(duì)值進(jìn)行合理的覆蓋,需要以下面的次序考慮屬性:

  1. 命令行參數(shù)
  2. 來(lái)自于java:comp/env的JNDI屬性
  3. Java系統(tǒng)屬性(System.getProperties())
  4. 操作系統(tǒng)環(huán)境變量
  5. 只有在random.*里包含的屬性會(huì)產(chǎn)生一個(gè)RandomValuePropertySource
  6. 在打包的jar外的應(yīng)用程序配置文件(application.properties,包含YAML和profile變量)
  7. 在打包的jar內(nèi)的應(yīng)用程序配置文件(application.properties,包含YAML和profile變量)
  8. 在@Configuration類上的@PropertySource注解
  9. 默認(rèn)屬性(使用SpringApplication.setDefaultProperties指定
  • 下面是一個(gè)具體的示例(假設(shè)你開(kāi)發(fā)一個(gè)使用name屬性的@Component):

    import org.springframework.stereotype.*
    import org.springframework.beans.factory.annotation.*
    @Component
    public class MyBean {
    @Value("${name}")
    private String name;
    // ...
    }
    
  • 你可以將一個(gè)application.properties文件捆綁到j(luò)ar內(nèi),用來(lái)提供一個(gè)合理的默認(rèn)name屬性值。當(dāng)運(yùn)行在生產(chǎn)環(huán)境時(shí),可以在jar外提供一個(gè)application.properties文件來(lái)覆蓋name屬性。對(duì)于一次性的測(cè)試,你可以使用特定的命令行開(kāi)關(guān)啟動(dòng)(比如,
    java -jar app.jar --name="Spring")。

配置隨機(jī)值

  • RandomValuePropertySource在注入隨機(jī)值(比如,密鑰或測(cè)試用例)時(shí)很有用。它能產(chǎn)生整數(shù),longs或字符串,比如:

      my.secret=${random.value}
      my.number=${random.int}
      my.bignumber=${random.long}
      my.number.less.than.ten=${random.int(10)}
      my.number.in.range=${random.int[1024,65536]}
    
  • random.int*語(yǔ)法是OPEN value (,max) CLOSE,此處OPEN,CLOSE可以是任何字符,并且value,max是整數(shù)。如果提供max,那么value是最小的值,max是最大的值(不包含在內(nèi))。

訪問(wèn)命令行屬性

  • 默認(rèn)情況下,SpringApplication將任何可選的命令行參數(shù)(以'--'開(kāi)頭,比如,--server.port=9000)轉(zhuǎn)化為property,并將其添加到Spring Environment中。如上所述,命令行屬性總是優(yōu)先于其他屬性源。
  • 如果你不想將命令行屬性添加到Environment里,你可以使用SpringApplication.setAddCommandLineProperties(false)來(lái)禁止它們。

Application屬性文件

  • SpringApplication將從以下位置加載application.properties文件,并把它們添加到Spring Environment中:
  1. 當(dāng)前目錄下的一個(gè)/config子目錄
  2. 當(dāng)前目錄
  3. 一個(gè)classpath下的/config包
  4. classpath根路徑(root)
  • 這個(gè)列表是按優(yōu)先級(jí)排序的(列表中位置高的將覆蓋位置低的)。

注:你可以使用YAML('.yml')文件替代'.properties'。

  • 如果不喜歡將application.properties作為配置文件名,你可以通過(guò)指定spring.config.name環(huán)境屬性來(lái)切換其他的名稱。你也可以使用spring.config.location環(huán)境屬性來(lái)引用一個(gè)明確的路徑(目錄位置或文件路徑列表以逗號(hào)分割)。

      $ java -jar myproject.jar --spring.config.name=myproject
      //or
      $ java -jar myproject.jar --  spring.config.location=classpath:/default.properties,classpath:/override.properties
    
  • 如果spring.config.location包含目錄(相對(duì)于文件),那它們應(yīng)該以/結(jié)尾(在加載前,spring.config.name產(chǎn)生的名稱將被追加到后面)。不管spring.config.location是什么值,默認(rèn)的搜索路徑classpath:,classpath:/config,file:,file:config/總會(huì)被使用。以這種方式,你可以在application.properties中為應(yīng)用設(shè)置默認(rèn)值,然后在運(yùn)行的時(shí)候使用不同的文件覆蓋它,同時(shí)保留默認(rèn)配置。

注:如果你使用環(huán)境變量而不是系統(tǒng)配置,大多數(shù)操作系統(tǒng)不允許以句號(hào)分割(period-separated)的key名稱,但你可以使用下劃線(underscores)代替(比如,使用SPRING_CONFIG_NAME代替spring.config.name)。如果你的應(yīng)用運(yùn)行在一個(gè)容器中,那么JNDI屬性(java:comp/env)或servlet上下文初始化參數(shù)可以用來(lái)取代環(huán)境變量或系統(tǒng)屬性,當(dāng)然也可以使用環(huán)境變量或系統(tǒng)屬性。

特定的Profile屬性

  • 除了application.properties文件,特定配置屬性也能通過(guò)命令慣例application-{profile}.properties來(lái)定義。特定Profile屬性從跟標(biāo)準(zhǔn)application.properties相同的路徑加載,并且特定profile文件會(huì)覆蓋默認(rèn)的配置。

屬性占位符

  • 當(dāng)application.properties里的值被使用時(shí),它們會(huì)被存在的Environment過(guò)濾,所以你能夠引用先前定義的值(比如,系統(tǒng)屬性)。

      app.name=MyApp
      app.description=${app.name} is a Spring Boot application
    

注:你也能使用相應(yīng)的技巧為存在的Spring Boot屬性創(chuàng)建'短'變量。

使用YAML代替Properties

  • YAML是JSON的一個(gè)超集,也是一種方便的定義層次配置數(shù)據(jù)的格式。無(wú)論你何時(shí)將SnakeYAML 庫(kù)放到classpath下,SpringApplication類都會(huì)自動(dòng)支持YAML作為properties的替換。

注:如果你使用'starter POMs',spring-boot-starter會(huì)自動(dòng)提供SnakeYAML。

加載YAML
  • Spring框架提供兩個(gè)便利的類用于加載YAML文檔,YamlPropertiesFactoryBean會(huì)將YAML作為Properties來(lái)加載,YamlMapFactoryBean會(huì)將YAML作為Map來(lái)加載。
    示例:

    environments:
        dev:
            url: http://dev.bar.com
            name: Developer Setup
        prod:
            url: http://foo.bar.com
            name: My Cool App
    

上面的YAML文檔會(huì)被轉(zhuǎn)化到下面的屬性中:

environments.dev.url=http://dev.bar.com
environments.dev.name=Developer Setup
environments.prod.url=http://foo.bar.com
environments.prod.name=My Cool App

YAML列表被表示成使用[index]間接引用作為屬性keys的形式,例如下面的YAML:

my:
   servers:
       - dev.bar.com
       - foo.bar.com

將會(huì)轉(zhuǎn)化到下面的屬性中:

    my.servers[0]=dev.bar.com
    my.servers[1]=foo.bar.com
  • 使用Spring DataBinder工具綁定那樣的屬性(這是@ConfigurationProperties做的事),你需要確定目標(biāo)bean中有個(gè)java.util.List或Set類型的屬性,并且需要提供一個(gè)setter或使用可變的值初始化它,比如,下面的代碼將綁定上面的屬性:

      @ConfigurationProperties(prefix="my")
      public class Config {
          private List<String> servers = new ArrayList<String>();
          public List<String> getServers() {
          return this.servers;
          }
      }
    
在Spring環(huán)境中使用YAML暴露屬性
  • YamlPropertySourceLoader類能夠用于將YAML作為一個(gè)PropertySource導(dǎo)出到Spring Environment。這允許你使用熟悉的@Value注解和占位符語(yǔ)法訪問(wèn)YAML屬性。

  • Multi-profile YAML文檔

  • 你可以在單個(gè)文件中定義多個(gè)特定配置(profile-specific)的YAML文檔,并通過(guò)一個(gè)spring.profiles key標(biāo)示應(yīng)用的文檔。例如:

      server:
          address: 192.168.1.100
      ---
      spring:
          profiles: development
      server:
          address: 127.0.0.1
      ---
      spring:
          profiles: production
      server:
          address: 192.168.1.120
    
  • 在上面的例子中,如果development配置被激活,那server.address屬性將是127.0.0.1。如果development和production配置(profiles)沒(méi)有啟用,則該屬性的值將是192.168.1.100。

YAML缺點(diǎn)
  • YAML文件不能通過(guò)@PropertySource注解加載。所以,在這種情況下,如果需要使用@PropertySource注解的方式加載值,那就要使用properties文件。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容