1. 程式人生 > >SpringBoot基礎篇配置資訊之多環境配置資訊

SpringBoot基礎篇配置資訊之多環境配置資訊

前面一篇主要介紹的是如何獲取配置資訊,接下來則是另外一個非常非常基礎和必要的知識點了,應用如何根據不同的環境來選擇對應的配置,即配置的多環境選擇問題

I. 多環境配置

配置區分環境,最直觀的如測試環境和生產環境的DB不同,測試環境的應用要求連線測試DB;生成環境的應用要求連生成DB;對於應用本身來說,業務程式碼啥的都是一樣,無非就是DB的配置不同,如果在程式碼中寫死環境判斷,然後進行選擇配置話,就不太優雅了;

SpringBoot本身就支援多環境配置檔案,應用的配置,除了 application.yml 檔案之外,還會有環境相關的配置,如下一個例項

application.yml
application-dev.yml
application-pro.yml

1. 多環境選擇

a. 命令規則

配置檔案,一般要求是以 application 開頭,可以是yml檔案也可以是properties檔案

b. 配置選擇

如何確定哪個配置配置檔案(application-dev.yml 與 application-pro.yml)生效呢?

  • 通過配置資訊 spring.profile.active 來指定需要載入的配置檔案

通常這個配置資訊會放在 applicatin.yml 檔案中,如下

spring:
  profiles:
    active: dev

上面這個表示,當前的配置資訊,會從 application.ymlapplication-dev.yml

檔案中獲取;且-dev檔案中定義的配置資訊,會覆蓋前面的配置資訊

注意

  • 上面這個配置的value,可以指定多個配置檔案,用英文逗號分隔
  • 其中最右邊的優先順序最高,覆蓋左邊配置檔案中重名的配置資訊

c. 例項演示

配置檔案內容如下

application.yml

# 埠號
server:
  port: 8081

spring:
  profiles:
    active: dev,biz


biz:
  total: application

application-dev.yml

biz:
  env: dev-environment
  profile: dev-profile

application-pro.yml

biz:
  env: pro-environment
  profile: pro-profile

application-biz.yml

biz:
  whitelist: a,b,c,d,e,f,g
  ratelimit: 1,2,3
  total: application-biz
  profile: biz-profile

通過前面的規則進行分析,當前選中生效的配置檔案為

  • application.yml, application-dev.yml, application-biz.yml
  • 優先順序為:biz檔案的配置覆蓋dev檔案,dev檔案的覆蓋application的配置

程式碼驗證如下

package com.git.hui.boot.properties;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.Environment;

/**
 * Created by @author yihui in 09:17 18/9/20.
 */
@SpringBootApplication
public class Application {

    public Application(Environment environment) {
        String env = environment.getProperty("biz.env");

        String whitelist = environment.getProperty("biz.whitelist");
        String ratelimit = environment.getProperty("biz.ratelimit");

        String total = environment.getProperty("biz.total");
        String profile = environment.getProperty("biz.profile");

        // application.yml檔案中的配置 spring.profile.active指定具體選中的配置檔案,為 application-dev 和 application-biz
        // read from application-dev.yml
        System.out.println("env: " + env);

        // read from application-biz.yml
        System.out.println("whitelist: " + whitelist);
        System.out.println("ratelimit: " + ratelimit);


        // 當配置檔案 application.yml, application-dev.yml, application-biz.yml 三個檔案都存在時,覆蓋規則為
        // biz > dev > application.yml  (其中 biz>dev的原則是根據 spring.profile.active 中定義的順序來的,最右邊的優先順序最高)
        // read from application-biz.yml
        System.out.println("total: " + total);

        // read from application-biz.yml
        System.out.println("profile: " + profile);
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }

}

輸出結果為

env: dev-environment
whitelist: a,b,c,d,e,f,g
ratelimit: 1,2,3
total: application-biz
profile: biz-profile

2. 優先順序問題

上面雖然看是實現了多環境的配置問題,但看完之後有一個明顯的疑問,選擇環境的配置資訊寫死在application.yml檔案中,難道說部署到測試和生產環境時,還得記得手動改這個配置的值麼?

如果是這樣的話,也太容易出問題了吧。。。

那麼如何解決這個問題呢,常見的一種方式是通過啟動指令碼,傳入當前環境的引數,來覆蓋選中的環境

a. 配置檔案優先順序

預設的配置檔案是放在 src/main/resources 目錄下,當然也是可以放其他位置的

  • 外接,在相對於應用程式執行目錄的 /config 子目錄中
  • 外接,在應用程式執行的目錄中
  • 內建,放在config包下(即 src/main/resources/config)目錄下
  • 內建,放在classpath根目錄下(即預設的 src/main/resources/目錄下)

上面的優先順序是從高到低來的,即外接的改與內建的;config下面的高於根目錄下的

以內建的兩個進行對比,實測結果如下

優先順序對比測試

b. 配置資訊來源

前面一篇中,遺留了一個問題,就是在配置檔案中配置了屬性 user.name = 一灰灰blog, 但是實際取出的卻是 user (我個人的電腦使用者名稱),也就是說,Environment中讀取的配置資訊,不僅僅是從配置檔案中獲取,還要其他的一些配置資訊來源

根據優先順序對屬性來源進行排序,如下

  • 根目錄下的開發工具全域性設定屬性(當開發工具啟用時為~/.spring-boot-devtools.properties)。
  • 測試中的@TestPropertySource註解。
  • 測試中的@SpringBootTest#properties註解特性。
  • 命令列引數
  • SPRING_APPLICATION_JSON中的屬性(環境變數或系統屬性中的內聯JSON嵌入)。
  • ServletConfig初始化引數。
  • ServletContext初始化引數。
  • java:comp/env裡的JNDI屬性
  • JVM系統屬性
  • 作業系統環境變數
  • 隨機生成的帶random.* 字首的屬性(在設定其他屬性時,可以應用他們,比如${random.long})
  • 應用程式以外的application.properties或者appliaction.yml檔案
  • 打包在應用程式內的application.properties或者appliaction.yml檔案
  • 通過@PropertySource標註的屬性源
  • 預設屬性(通過SpringApplication.setDefaultProperties指定).

3. 環境選擇的幾種方式

看了上面的配置資訊來源,我們可以如何優雅的實現不同環境選擇不同的配置檔案呢?有下面兩個容易想到和實現的方式了

  • 命令列引數
  • 應用程式外的配置檔案

a. 命令列引數方式

這種實現思路就是在啟動指令碼中,傳入當前環境,然後覆蓋掉屬性 --spring.profiles.active,對業務來說,就不需要做任何的改動了,只要啟動指令碼本身區分環境即可,唯一的要求就是遵循統一的規範,一個簡單的實現如下

假定命令列的第一個引數就是環境,取出這個引數,傳入即可

public static void main(String[] args) {
      if (args.length > 0) {
          SpringApplication.run(Application.class, "--spring.profiles.active=" + args[0] + ",biz");
      } else {
          SpringApplication.run(Application.class);
      }
  }

實測結果,注意下面紅框內的pro,覆蓋了配置檔案中的dev

配置覆蓋測試

說明

當然可以直接傳入完整的命令列引數--spring.profiles.active=pro,biz,這樣程式碼內部就不需要進行特殊處理

b. 外接配置檔案方式

當程式以獨立的jar執行時,我個人的感覺是外接的配置檔案是優於內建的配置檔案的;因為修改配置的話,不需要重新打包部署,直接改即可

這種實現方式也沒啥好多說的,相當於把配置檔案拉出來放在外面而已,再根據環境寫具體的spring.profiles.active的值

II. 小結

  1. SpringBoot是支援多環境的配置,通過配置屬性 spring.profiles.active 來指定
  2. spring.profiles.active引數指定多個配置檔案時,右邊的優於左邊的
  3. 應用外的配置檔案優先於應用內,config目錄下的優先於根目錄下的
  4. 配置引數來源及優先順序可以參看前文: 配置資訊來源
  5. 命令列引數傳入時,請注意寫法形同 --key=value

III. 其他

0. 專案

1. 一灰灰Blog

一灰灰的個人部落格,記錄所有學習和工作中的博文,歡迎大家前去逛逛

2. 宣告

盡信書則不如,已上內容,純屬一家之言,因個人能力有限,難免有疏漏和錯誤之處,如發現bug或者有更好的建議,歡迎批評指正,不吝感激

  • QQ: 一灰灰/3302797840

3. 掃描關注

一灰灰blog

QrCode

知識星球

goals