1. 程式人生 > >天啦!竟然從來沒有人講過 SpringBoot 支援配置如此平滑的遷移

天啦!竟然從來沒有人講過 SpringBoot 支援配置如此平滑的遷移

SpringBoot 是原生支援配置遷移的,但是官方文件沒有看到這方面描述,在原始碼中才看到此模組,spring-boot-properties-migrator,幸虧我沒有跳過。看到這篇文章的各位,可算是撿到寶了,相信你繼續往下看下去,定會忍不住點贊、收藏、關注。

效果

先放個效果吸引你 :)

從 SpringBoot 2.0.0 版本開始,配置服務上下文,不支援 server.context-path,而需要server.servlet.context-path配置。但是隻要加上以下一個官方依賴,就可以支援使用 server.context-path

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-properties-migrator</artifactId>
    </dependency>

server.context-path 所對應的屬性 ServerProperties#contextPath 在 Java 程式碼中已不存在,server.servlet.context-path 所對應的的屬性在內部類 Servlet 中才有,為何加了此依賴就能實現如此神奇的效果呢。

原理

SpringBoot 對外部化配置原生支援遷移功能,所謂遷移,具體是指對應配置的屬性名變動,仍可以使用原來的屬性名配置。
spring-configuration-metadata.json 的資訊可以輔助 IDE 進行配置的提示,也可以用來完成配置的遷移。非常的簡單。

相關文章: SpringBoot 配置提示功能

通過閱讀程式碼,獲得以下資訊:

  1. 監聽 ApplicationPreparedEvent 事件(即:環境已準備事件),執行以下操作並收集資訊
  2. classpath*:/META-INF/spring-configuration-metadata.json 中載入所有配置
  3. 從上下文的 environment 中過濾出提示的配置(滿足條件:1. deprecation 不為 null,且提示 level 為 error)
  4. 判斷是否相容(相容條件見下一節),提取出相容的屬性
  5. 將 value 對應到 replacement 的 key,並將其屬性源命名為:migrate-原名
  6. 將配置遷移的新屬性源新增到 environment 中,且新增
    到原屬性源之前(優先順序高)。
  7. 監聽事件:ApplicationReadyEvent(應用上下文已準備) 或 ApplicationFailedEvent(應用啟動失敗),列印以上步驟收集的遺留配置資訊。以 warn 級別列印相容的配置,以 error 級別列印不相容的配置

配置相容條件

根據元資料中定義的 type 判斷

  1. 如果舊型別、新型別其中之一為 null(元資料中未指定),則不相容
  2. 如果兩個型別一樣,相容
  3. 如果新型別是 Duration,而舊型別是 Long 或 Integer,則相容
  4. 其他情況視為不相容
  5. environment 中取配置資訊,理論上支援 SpringBoot 所有的配置方式。

效果

相容效果:
棄用屬性(如果還存在)與替換後的屬性都會使用配置檔案中的棄用的屬性名所對應的的值。

總結

使用配置遷移功能,需要以下步驟:

  1. 引入依賴:spring-boot-properties-migrator(支援配置遷移)、spring-boot-configuration-processor(生成元資料檔案,如果已經有完整的,不需要此依賴)
  2. 元資料檔案spring-configuration-metadata.json 中棄用屬性名對應的 properties 中必須有 deprecation(在additional-spring-configuration-metadata.json 中新增,相關文章: SpringBoot 配置提示功能)
  3. deprecation 中需指定 level 為 error
  4. deprecation 中需指定 replacement
  5. replacement 對應的屬性配置在元資料檔案中存在,與棄用屬性相容

經典示例之配置上下文

再說回一開始展示的配置上下文示例。

# 配置 servlet 服務上下文
server:
  context-path: test

從 SpringBoot 2.0.0 版本開始,以上配置不支援,點到配置元資料檔案中(spring-configuration-metadata.json),發現如下資訊:

{
  "properties": [
    {
      "name": "server.context-path",
      "type": "java.lang.String",
      "description": "Context path of the application.",
      "deprecated": true,
      "deprecation": {
        "level": "error",
        "replacement": "server.servlet.context-path"
      }
    },
    {
      "name": "server.servlet.context-path",
      "type": "java.lang.String",
      "description": "Context path of the application.",
      "sourceType": "org.springframework.boot.autoconfigure.web.ServerProperties$Servlet"
    }

替換屬性名為:server.servlet.context-path,此屬性在org.springframework.boot.autoconfigure.web.ServerProperties 中,且在類中可以發現,server.context-path 所對應的屬性 ServerProperties#contextPath 在程式碼中已不存在,而是在內部類 Servlet 中有,也就是對應 server.servlet.context-path 的屬性才有。

但是其滿足配置相容的條件,為什麼實際上使用卻好像不相容呢?
其實是因為沒有引入依賴,當引入依賴,就會發現此方式配置可以起作用。

示例之兩種屬性都存在

程式碼示例見 https://gitee.com/lw888/spring-boot-source-example/tree/master/properties-migrator

1、引入依賴

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-properties-migrator</artifactId>
</dependency>

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-configuration-processor</artifactId>
  <optional>true</optional>
</dependency>

2、Java 配置
此處故意保留棄用屬性

@Data
@Configuration
@ConfigurationProperties(prefix = "my")
public class MyProperties {
  /** the project name */
  private String name;

  private App app;

  @Data
  public static class App {
    private String name;
  }
}

3、元資料配置,spring-configuration-metadata.json 由程式生成,自定義配置放在 additional-spring-configuration-metadata.json

{
  "properties": [
    {
      "name": "my.name",
      "type": "java.lang.String",
      "description": "the project name.",
      "deprecation": {
        "reason": "test the properties-migrator feature.",
        "replacement": "my.app.name",
        "level": "error"
      }
    },
    {
      "name": "my.app.name",
      "type": "java.lang.String",
      "sourceType": "com.lw.properties.migrator.config.MyProperties$App",
      "description": "the project name."
    }
  ]
}

4、在 properties 或 yml 檔案中配置

my:
  name: lw
  app:
    name: app

5、列印配置資訊

@Slf4j
@SpringBootApplication
public class PropertiesMigratorApplication {

  public static void main(String[] args) {
    ConfigurableApplicationContext context =
        SpringApplication.run(PropertiesMigratorApplication.class, args);
    MyProperties myProperties = context.getBean(MyProperties.class);
    log.info("myProperties.name:{}", myProperties.getName());
    log.info(
        "myProperties$app.name:{}",
        Optional.ofNullable(myProperties.getApp()).orElse(new App()).getName());
  }
}

6、列印資訊如下:

2019-11-23 21:42:09.580 WARN 109408 --- [ main] o.s.b.c.p.m.PropertiesMigrationListener :
The use of configuration keys that have been renamed was found in the environment:

Property source 'applicationConfig: [classpath:/application.yml]':
Key: my.name
Line: 4
Replacement: my.app.name
Key: server.context-path
Line: 2
Replacement: server.servlet.context-path

Each configuration key has been temporarily mapped to its replacement for your convenience. To silence this warning, please update your configuration to use the new keys.
......... myProperties.name:lw
......... myProperties\(app.name:lw ......... serverProperties\)servlet.contextPath:/app

7、效果解析
在 yml 中棄用屬性名優先順序更高,棄用屬性與新屬性都使用此棄用屬性名對應的值。

參考資料

SpringBoot 2.2.1.RELEASE 原始碼
公眾號:逸飛兮(專注於 Java 領域知識的深入學習,從原始碼到原理,系統有序的學習)

相關推薦

竟然從來沒有 SpringBoot 支援配置如此平滑遷移

SpringBoot 是原生支援配置遷移的,但是官方文件沒有看到這方面描述,在原始碼中才看到此模組,spring-boot-properties-migrator,幸虧我沒有跳過。看到這篇文章的各位,可算是撿到寶了,相信你繼續往下看下去,定會忍不住點贊、收藏、關注。 效果 先放個效果吸引你 :) 從 Sp

【IT職業】從來沒有告訴你離職前要做的事 (收藏下,萬一哪用到了呢)

據哈佛商學院教授、《行動起來:擁抱不確定性並創造未來》一書的合著者倫納德·施萊辛格所說:“如同書擋一樣,你如何開始與如何結束,是任何職業關係中最為重要的部分。”但問題是,人們總是會花很多時間準備與策劃如何給別人留下深刻的第一印象,卻很少考慮到“最後印象”。無論你是為何理由

“媽媽,我不想學了”,你的回答改變孩子一生(悵然若失,說了一句話:“為什麼當初沒有人逼我?”。我不願意學,你就不讓我學啦!那時候我還小,我還不懂事,難道你也不懂事嗎。要做成一件事,就必須有延遲滿足的能力)

“媽媽,我不想學了”,你的回答改變孩子一生(組圖)新聞來源: 槽值 前兩天,送孩子去書法班的時候,在小區門口看到一位媽媽,她正拽著孩子往車裡進,孩子哭著掙扎:“我不想學舞蹈了,我不去,太累了……” 媽媽怒吼著:“你今天去也得去,不去也得給我去!” 最終,孩子還是拗不過媽媽,上了車,去學舞蹈。 我不禁想

列印日誌竟然只曉得 Log4j?

空了的時候,我都會在群裡偷偷摸摸地潛水,對小夥伴們的一舉一動、一言一行篩查診斷。一副班主任的即時感,讓我感到非常的快樂,略微夾帶一絲絲的枯燥。 這不,我在戰國時代讀者群裡發現了這麼一串聊天記錄: 竟然有小夥伴不知道“打日誌”是什麼意思,不知道該怎麼學習,還有小夥伴回答說,只知道 Log4j! 有那麼一刻,

,微信開發者工具預設竟然沒有開啟檔案儲存格式化功能,正確的開啟姿勢請看這裡

前言 程式碼格式化對於程式設計師來說,是個高頻使用的功能。直接影響程式設計體驗,如果每次寫完程式碼後,還要手動排版,那寫程式碼得多費力,程式設計效率得多低。然而我驚訝的發現,微信開發者工具預設沒有開啟檔案儲存自動化格式開關,需要開發者自己去開啟,開啟之後,儲存js和json檔案時,會提示有兩個格式化擴充套件可

微職位課程強大升級,優惠最後一,明天就要恢復原價

漲價 活動 下班後的幾小時,你都在忙些什麽? 有的人下班之後約在一起逛吃逛吃,享受生活。有的人下班之後去了健身房,為自己的身體負責。還有的人,下班之後就開啟學霸模式,因為他們知道,超前學習就是要領先於別人,就算做不到進步,也一定不能落後!那麽沒報名微職位的同學,抓緊時間報名吧! 今年,微職位課程更新,

這股神秘的東方力量竟然攪動了世界杯

活動 12個 http 之前 cto 戰勝 公司 命運 到來 2018年俄羅斯世界杯在6月27日淩晨2兩點,一場決定阿根廷的命運的比賽兩點到來,在此前進行的D組的兩場比賽中,阿根廷平一負一,在小組中積-3分,排名小組第四,只有戰勝尼日利亞,才有可能出現。比賽開始,上半場第1

滴滴出行瘋狂招

php 生活 rip ued 競爭 bte reac 加油 創投 滴滴出行瘋狂招人啦! 級別D6、D7、D8,職位包括前端、後端、產品、測試,我們只看能力,其他不限! 業務: 涉及汽車服務領域租售、維保、加油、分時、車生活等等,未來萬億級市場,潛力巨大,增長迅猛!

號外、號外2019安校園招聘簡歷投遞方式更換

號外、號外!2019安天校園招聘簡歷投遞方式更換啦! 【我們要搞事情啦!】 有意向的同學請將簡歷投遞至郵箱 [email protected]   郵箱主題以及簡歷命名格式為:學校  姓名 應聘崗位 學歷 ,歡迎繼續投遞!!!  無畏前行十八

從來沒有任何一篇文章會把“程式設計師認知”如此透徹

程式猿問科比:“你為什麼這麼成功? ” 科比:“你知道洛杉磯凌晨四點是什麼樣子嗎? ” 程式猿:“知道,一般那個時候我還在寫程式碼,怎麼了?” 科比:“額…….” 你以為程式設計師都是這樣生活的: 別瞎,他們只是在歷劫! 度過這段日子,他們就飛昇上仙,乃至上神。過上另

感謝一路相伴的朋友們我的個人工作室招

大家好,又來和大家嘮叨了。首先呢,在這裡要感謝大家一下。在我找不到工作的期間,隨意寫了一點當時自己的想法,竟然有這麼多朋友來關心和開導我,我很開心。在今年的6月份,我也是找到了我的第一份工作,而且還是在自己的老家。所以非常的開心,謝謝有你們一路的關心! 現在也已經進入了十一

#還真以為程式設計師沒有女朋友?不要被欺騙

程式設計師沒有女朋友一直是大家調侃的點,不知道是從何時開始“程式設計師找不到女朋友”這枚輿論的螺旋就轉開了。程式設計師身上有各種標籤,錢多、人傻、直男癌、木訥…… 從客觀的角度來說,程式設計師行業的高薪毋庸置疑,舉幾個例子: 當你用力擠了擠一週的生活費,去星巴

3602: 中獎(史上最強水解沒有之一

3602: 中獎啦!  時間限制(普通/Java):1000MS/3000MS     記憶體限制:65536KByte 描述 L超時由於最近銷售量特別好。為答謝廣大的顧客,L公司準備舉行抽獎活動。而規則如下:超市會發行一批刮獎卡,每張刮獎卡刮開上面的圖層會

哈哈哈哈哈哈哈我們都在1000的大群裡,太好玩驚喜太多…

揮手告別2018年,我們開始擁抱2019年啦!!! 你>>>>>>>是否還因為找不到組織而迷茫 莫慌莫慌,今天小編要給大家分享一波技術大群 在這裡, 你不僅能與大牛探討問題、探討技術、探討人生 還能。。。。。。 找到志同道合的道

#CSDN刷票門# 有沒有在惡意刷票?CSDN請告訴我用24小時監控資料說話

特別宣告: 此次並非針對其他參與2013中國十大優秀開源專案的同行,體系有漏洞要譴責的是制定規則並從中獲益但不作為的權貴,草根們制定不了規則但可發現和利用漏洞,這是程式設計師應有反叛精神沒錯。但被作為道具不可接受。我代表FineUI請求CSDN公開資料,如果您覺得CSDN有必要撕下遮羞布,請共同呼籲。

沒有喜歡聽廢話——重點

-s 同學 身邊 喜歡 error tip 解釋 med white 這是我自己身上最大的一個缺點——也是我必須要改變的 以下是我自己個人的一些想法,做如下記錄:(期待下一次的進步) 通過幾個場

生產機器連線數飆升到上萬,背後發生了什麼?

個人部落格地址 studyidea.cn,點選檢視更多原創文章 0x00. 翻車現場 那是個月黑風高的夜晚,小黑哥成功將新版本釋出到了生產,小心翼翼檢查了應用日誌,後續測試小姐姐驗收成功。 恩,小黑哥我還是一如既往的穩~ 接著小黑哥就跑到樓下食堂吃個夜宵,誰知正吃到一半,線上運維同學發來幾條告警資訊,

手動編寫mybatis雛形竟然這麼簡單

# 前言 mybaits 在ORM 框架中,可算是半壁江山了,由於它是輕量級,半自動載入,靈活性和易拓展性。深受廣大公司的喜愛,所以我們程式開發也離不開mybatis 。但是我們有對mabtis 原始碼進行研究嗎?或者想看但是不知道怎麼看的苦惱嗎? ![在這裡插入圖片描述](https://img2020.c

知道硬碟很慢,但沒想到比 CPU L1 Cache 慢 10000000 倍

前言 大家如果想自己組裝電腦的話,肯定需要購買一個 CPU,但是儲存器方面的裝置,分類比較多,那我們肯定不能只買一種儲存器,比如你除了要買記憶體,還要買硬碟,而針對硬碟我們還可以選擇是固態硬碟還是機械硬碟。 相信大家都知道記憶體和硬碟都屬於計算機的儲存裝置,斷電後記憶體的資料是會丟失的,而硬碟則不會,因為硬