(8) Spring Boot的Properties與Profile

Albert Hg
learning-from-jhipster
13 min readSep 18, 2020

本篇內容的程式碼於 Spring_6_SpringProperties

不曉得你有沒有發現啟動服務的時候,port 的預設值都是8080,如果想要改成其他的 port,該怎麼辦呢?

這時候我們就必須來認識一下甚麼是「properties」與「profile」了。

Spring Boot Properties 的內容

Spring Boot 的 Properties 有許多可以設置的內容,可以在下方網址中找到所有可以對 Spring Boot 進行設定的參數:

https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html

例如我們找到「server.port」,可以看到其預設值為8080,說明為「Server HTTP port.」

因此我們就可以透過這個參數的修改,來指定當服務啟動時的 port 位置。

其他還有許多可以設定的參數,Spring Boot 幫我們分類了像是「Core properties」、「Web properties」、「Security properties」等等之類的設定參數,可以大致參考一下內部細項的內容,但因為這裡礙於篇幅,所以就不做更仔細的介紹了。

Spring Boot Profile 的檔案位置

所謂的 Profile 代表的是設定那些 properties 參數的檔案。

還記得我們在一開始導入 Spring Boot 的時候有先加入「spring-boot-starter-parent」嗎,裏頭的包含了下方的片段設定:

代表 Spring Boot 所支援的 Profile 的檔名可以是「application*.yml」、「application*.yaml」以及「application*.properties」,並且 Profile 的許可路徑預設為「src/main/resources」底下的任意位置。

(如果你對於yaml、yml與properties不熟悉,可以參考這裡)

嘗試修改啟動服務的 port

原先 Spring Boot 啟動服務的預設位置為 8080,假設現在想要修改啟動的 port 位置為 8888,則可以這樣做:

  • 於「src/main/resources/configs/」底下建立一個「application.yml」的 Profile。
  • 於「application.yml」內加入如下 properties:
https://gist.github.com/albert-hg/db0498ceccbbb795def52a8d57597bc5
  • 執行「.\mvnw」

就可以看到如下訊息:

透過「server.port」這項 properties,可以修改啟動的 port 位置,圖片中顯示我們順利的將 port 改為 8888。

區分不同環境的 Profile

Properties 可以設定系統所需的一些參數,但更重要的是要可以針對不同環境使用不同的 Properties。

當我們在開發時,常常會因為不同的環境而有不同的配置,像是連接資料庫的配置、Log的配置或其他的基本配置。如果只有一份 Profile,那麼就得每次切換環境時,都要修改對應環境的 Properties,除了動作繁瑣之外,也容易造成錯誤。

因此我們就可以針對不同環境,建立不同的 Profile。

一樣拿 Service 啟動的 Port 為例子。例如想要在稱開發環境使用 port 8080,而在正式環境時想要使用 port 8090。此時就可以將 Properties 分做兩份,一份作為開發環境(application-development.yml),另一份作為正式環境(application-production.yml)。

https://gist.github.com/albert-hg/a64e08e2bcad5d3c20594cc3edca9958

到目前為止還只是將 profile 分成兩份,接著必須指定要以哪個 profile 作為 Spring 啟動時所吃的 profile。

有兩種作法,第一種為直接在 application.yml 中指定,第二種(比較常見)為執行 maven 時透過參數進行指定。

1. 在 application.yml 中指定 Profile

application.yml 是在啟動 Spring Boot 專案時,預設會吃的設定檔,因此如果我們想要指定使用不同環境的 profile,則可以在 application.yml 中進行設定。

Spring Boot Properties 中,有一參數可以設定 ─ spring.profiles.active,這個參數可以設定要使用哪些 profile。它的使用方式是,當賦予這個參數為某值時,則會以該值為後墜的 application-*.yml 作為 profile。

例如當你設定:「spring.profiles.active=ABC」,那麼 Spring Boot 就會將「application-ABC.yml」視為要使用的 profile。

此外他也可以支援使用多個 profile,以「,」作為多個 profile 的分界,例如當你設定:「spring.profiles.active=AAA,BBB」,那麼 Spring Boot 就會將「application-AAA.yml」以及「application-BBB.yml」視為要使用的 profile。

回到例子,我們建立好開發環境的 profile (application-development.yml)以及現場環境的 profile (application-production.yml)。因此假設現在我們執行 Spring Boot 專案時,想要執行的環境為現場環境,那麼就必須把 application.yml 中的 spring.profiles.active 設定為 production,如下:

https://gist.github.com/albert-hg/19ddc295a2db2a7c06fdb954515f6202

如此一來,在執行專案時,Spring Boot 就會將 application-production.yml 作為要使用的 profile了。也因此,當你在透過「.\mvnw」執行專案時,所使用的 port 就會為 8090。

但因為這樣還是要手動修改 application.yml 的 spring.profiles.active,這樣不夠彈性,所以你可以用接下來第二種方式來達成動態指定 profile 的目的。

2. 執行maven時透過參數指定 Profile

這沒有非常複雜,流程大概像下面這般敘述一樣:

  1. 於 pom.xml 內定義 profile 以及對應的 properties
  2. 執行「.\mvnw」的時候,使用 -P 的參數指定要使用哪個 profile 的設定
  3. application.yml 與 pom.xml 的 properties 對 spring.profiles.active 綁定
  4. Spring Boot 透過 application.yml 所綁定的值決定要使用哪個 profile

所以首先我們先在 pom.xml 中加入如下內容:

https://gist.github.com/albert-hg/2b05ca995d456c1ec4124c10a0295060

<profiles> 是 Maven 本身就有的內容,這邊只會簡單介紹這裡會用到的功能,但細節的部分可以參考下列網址:

https://maven.apache.org/guides/introduction/introduction-to-profiles.html

在<profiles>內的每一個<profile>比較重要的就是<id>以及<properties>的部分。

當使用 -P 參數(如下指令)時,裏頭所使用的參數代表的是「要使用的<profile>的<id>」。

.\mvnw -P <arg>

例如當輸入「.\mvnw -P prod」,則會使用<id>為 prod 的<profile>的內容。

在上述的 pom.xml 中,<id>為 dev 的<profile>內有一設定<activation>,底下的<activeByDefault>被設定為 true,代表若 -P 的參數沒有被指定時,則預設以這個<profile>進行<properties>的載入使用。

而<properties>則是代表使用了這個<profile>時所載入的properties,例如在目前所使用的範例中,使用<id>為 prod 的<profile>時,就會載入一個名為「activatedProperties」的 properties,讓專案啟動時使 pom.xml 有這個屬性值,且這個屬性值為「production」。

接著要將 application.yml 的 spring.profiles.active 與 activatedProperties 進行綁定,這樣才能在啟動專案時,讓 Spring Boot 可以吃到這個屬性。預設要讓 application.yml 的參數與 properties 進行綁定的字符是使用「@」。在現在這個範例中,要在 application.yml 綁定 activatedProperties 屬性的方式為「@activatedProperties@」,也就是將 application.yml 修改如下:

https://gist.github.com/albert-hg/b7a25d70a4435fd3397ba77f71fc7a73

關於使用「@」的說明可以參考如下網址,你也可以自定義想要使用的「字符」作為參數的綁定:

https://docs.spring.io/spring-boot/docs/1.4.x/reference/html/howto-properties-and-configuration.html

如此,就能透過「.\mvnw -P dev」或「.\mvnw -P prod」使 application.yml 底下的 spring.profiles.active 動態的被設定為 「development」 或是「production」,也代表能動態的決定使用「application-development.yml」或是「application-production.yml」的設定檔了。

執行maven時透過參數指定「多個」 Profile

還記得在 application.yml 的 spring.profiles.active 參數中,他可以載入多個 profile 嗎?每當載入了 profile 時,其實你可以將此行為視為「擴展」。

假設有兩個profile, application-AAA.yml 以及 application-BBB.yml ,當設定 application.yml 的「spring.profiles.active=AAA,BBB」時,也就是說 Spring Boot 會先載入 application.yml ,接著讀取 application-AAA.yml 的設定並覆蓋先前載入的 properties,接著再讀取 application-BBB.yml 的設定並覆蓋先前載入的 properties,以達到「擴展」的功能。

而 Maven 的 -P 參數一樣也可以達到同時讀取多個 <profile> 的功能,也是以「,」分開想要依序讀取的<profile>的<id>。假設你建立了一個擴展的 profile 叫做 application-extension.yml 並修改 pom.xml 如下:

https://gist.github.com/albert-hg/2684038cdec396957b1e98cc7fac5b17

在 pom.xml 的一開始,就已經有先定義好了名為「profile.extension」的properties,其初始值為空值,而在整個 pom.xml 中都可以透過「${}」的方法來取得指定的 properties 的值,例如「${profile.extension}」。

使用「.\mvnw」,因為預設 -P 會是<id>為 dev 的<profile>,同時在一開始就有先給了 profile.extension 預設值(空值),因此 activatedProperties 的值就會是「development」。

而使用「.\mvnw -P prod,ext」, 會先載入<id>為 prod 的<profile>,接著再載入<id>為 ext 的<profile>,使 profile.extension 的值從空值變成了「,extension」,因此 activatedProperties 的值是「production,extension」。最後 Spring Boot 在載入 application.yml 的 spring.profiles.active 時,就可以透過「@activatedProperties@」的綁定來讀取 application-production.yml 以及 application-extension.yml 的 profile 了。

文末

在這篇文章中介紹了 Spring Boot 的 properties 的使用方式,接著說明如何建立多個 profile 以適用於不同環境的 properties,並更進一步的展示如何同時載入多份 profile以用於擴展。

目前在 properties 與 profile 的介紹到這邊先告一個段落,在後續的內容中,會開始大量地使用到 properties 的設定(這也是為什麼必須先有這篇文章的原因),之後還會出現需要自定義 properties 的部分,不過那會等之後遇到的時候再來說明XD。

下一篇文章將介紹如何於專案導入 Logging,會先簡單的介紹一下有哪些是常見的Logging,接著說明服用方式,那我們就繼續看下去吧!

--

--

Albert Hg
learning-from-jhipster

I am a programmer but love other things. I am a nobody but keep myself going. I am a person who wishes to reach the heaven but lost the wings.