1. 程式人生 > >Maven Profile 與 Spring Profile 管理多環境打包

Maven Profile 與 Spring Profile 管理多環境打包

一般開發團隊會有多個部署環境,如 dev 環境用於開發自測,QA 環境讓測試團隊測試, Production 環境作為線上環境。通常不同環境的配置不同,我們希望打包時的人力消耗最少。

#Spring Boot Profile

Spring Boot Profile 有許多的功能,這裡只說管理配置的內容。Spring 載入配置的順序如下:

  1. Jar 包外的 application-{profile}.properties
  2. Jar 包內的 application-{profile}.properties
  3. Jar 包外的 application.properties
  4. Jar 包內的 application.properties

例如,如果我們在 application.properties 中指定

spring.profiles.active = dev

則 spring 會使用 application-dev.properties 檔案中的配置來覆蓋 application.properties 檔案中的相應配置。

#Maven Profile

如果用的不是 Spring 要怎麼管理多個 Profile 呢?可以從構建工具 Maven 下手。

Maven 也提供了 Profile 支援,它允許我們在 pom.xml 中定義多個 Profile ,每個 profile 可以指定自己的一些配置、依賴、觸發條件等。例如:

<profiles>    <profile>        <id>dev</id>        <activation>            <activeByDefault>true</activeByDefault>        </activation>        <properties>            <profile.active>dev</profile.active>        </properties>    </profile
>
<profile> <id>prod</id> <properties> <profile.active>prod</profile.active> </properties> </profile></profiles>

上面指定了兩個 profile: devprod,其中 dev 是預設啟用的,當profile 被啟用時,它定義的的屬性、依賴等內容就會起效。這裡我們定義了profile.active 屬性,之後會用到。

在編譯時指定 mvn clean install -Pprod 就能切換成 prod profile。

#多環境打包的具體步驟

Maven 與 Spring Profile 的功能是有重合的,只使用一種其實就能實現多環境多配置。但它們各有千秋:

  • Spring profile 除了指定配置,還有一些其它作用(如為不同的 profile 生成不同的 bean),但每次打包前都需要手工指定啟用哪個 profile
  • Maven Profile 可以通過命令列指定使用的 profile,但缺少了 spring profile 的一些特定功能。

因此我們希望融合二者,取長補短。步驟如下:

#在 pom.xml 中定義 Profile

這裡跟上面介紹的一樣,定義兩個/多個 profile 併為各個 profile 指定自己的屬性:

<profiles>    <profile>        <id>dev</id>        <activation>            <activeByDefault>true</activeByDefault>        </activation>        <properties>            <profile.active>dev</profile.active>        </properties>    </profile>    <profile>        <id>prod</id>        <properties>            <profile.active>prod</profile.active>        </properties>    </profile></profiles>

#在 pom.xml 中定義資源過濾

目的是為了讓 maven 在構建時用 profile 中指定的屬性來替換 application.properties 中的內容。

<resources>    <resource>        <directory>src/main/resources</directory>        <!--①-->        <excludes>            <exclude>application*.properties</exclude>        </excludes>    </resource>    <resource>        <directory>src/main/resources</directory>        <!--②-->        <filtering>true</filtering>        <includes>            <include>application.properties</include>            <include>application-${profile.active}.properties</include>        </includes>    </resource></resources>

①中,我們通過 excludes 來將所有的 application*.properties 排除在外,這樣 maven 在打包時就不會複製這些檔案。畢竟我們不希望把 application-dev.properties 也包含在 prod 的 jar 包裡。

②中,通過開啟 filtering,maven 會將檔案中的 @[email protected] 替換 profile 中定義的 XX 變數/屬性。另外,我們還通過 includes 來告訴 maven 根據profile 來複制對應的 properties 檔案。

#用 Maven 變數指定 Spring Profile

application.properties 檔案中加入下面這行:

spring.profiles.active = @[email protected]

這裡 profile.active 是在 maven profile 中的 properties 定義的,而 @[email protected] 的語法則是上節提到的 maven filtering 替換變數的語法。

#構建不同的包

mvn clean package -P<profile_name>

#與 Intellij IDEA 整合

IDEA 在 Build 時並不會處理 Maven Profile 的 filtering 設定,在 Run 的時候會直接複製 application.properties 檔案到 target/class 目錄下,而由於檔案中包含 @[email protected](沒有被 maven 替換)且 @ 是非法字元,因此沒有辦法執行。

解決方法是讓 IDEA Run 之前執行 mvn resources:resouces,如下圖:

#小結

Maven profile 與 Spring profile 有自的優點,結合起來的步驟如下:

  1. pom.xml 中定義多個 profile 及自己的屬性
  2. pom.xml 中定義 resource filtering,一方面控制 jar 中包含的資原始檔,一方面允許 @[email protected] 的變數替換
  3. application.properties 中指定 spring.profiles.active,值為 maven profile 中定義的屬性。
  4. 構建時使用 mvm clean package -P<profile> 來指定 profile。

#參考