目錄
4、Spring profile與Maven Profile 融合二者,取長補短 實現 多環境打包
1、使用場景
因爲實際項目之中,經常使用到針對不同環境進行相關的打包。於是趁最近一段時間比較閒。研究了一下如何是現在在多環境下打包問題。本片文章實現了基於*.properties文件及 *.yml文件的多環境打包。本片文章使用的是基於Maven的Profile,同時使用Maven的過濾器(filtering)。
一般開發團隊會有多個部署環境,如 dev 環境用於開發自測,Test環境讓測試團隊測試, Production 環境作爲線上環境。通常不同環境的配置不同,我們希望打包時的人力消耗最少。
需要注意下:本文裏面雖然都實現了*.properties和.yml文件的多環境下指定某個環境進行打包。但是有一個問題比較糟心就是基於*.properties文件類型的多環境打包時候,在application.properties文件之中中文被轉換爲了 Unicode碼。希望其他看到此文的人能夠提供好的解決方案。雖然功能可以實現指定環境直接替換,這是唯一的缺陷。
其他的.yml文件的替換很正常的。
2、Spring Boot Profile
Spring Boot Profile 有許多的功能,這裏只說管理配置的內容。Spring 加載配置的順序如下:
- Jar 包外的
application-{profile}.properties
- Jar 包內的
application-{profile}.properties
- Jar 包外的
application.properties
- Jar 包內的
application.properties
例如,如果我們在 application.properties
中指
spring.profiles.active = prod
則 SpringBoot 會使用 application-prod.properties
文件中的配置來覆蓋 application.properties
文件中的相應配置。
3、Maven Profile設置
Maven 也提供了 Profile 支持,它允許我們在 pom.xml
中定義多個 Profile ,
每個 profile 可以指定自己的一些配置、依賴、觸發條件等。例如:
<profiles>
<profile>
<id>dev</id><!-- 開發環境 -->
<properties>
<active.target.profile>dev</active.target.profile>
</properties>
</profile>
<profile>
<id>test</id><!-- 測試環境 -->
<properties>
<active.target.profile>test</active.target.profile>
</properties>
</profile>
<profile>
<id>prod_test</id><!-- 生測環境 -->
<properties>
<active.target.profile>prod_test</active.target.profile>
</properties>
</profile>
<profile>
<id>prod</id><!-- 生產環境 -->
<properties>
<active.target.profile>prod</active.target.profile>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
</profiles>
上面指定了四個 profile: dev、test、prod_test、
prod
,其中 prod
是默認啓用的,當profile 被啓用時,它定義的的屬性、依賴等內容就會起效。這裏我們定義了spring.profiles.active
屬性(可以自己命名爲其他的只要對應上關係即可),之後會用到。
在編譯時指定 mvn clean install -Pprod
就能切換成 prod
profile。
4、Spring profile與Maven Profile 融合二者,取長補短 實現 多環境打包
Maven 與 Spring Profile 的功能是有重合的,只使用一種其實就能實現多環境多配置。但它們各有千秋:
- Spring profile 除了指定配置,還有一些其它作用(如爲不同的 profile 生成不同的 bean),但每次打包前都需要手工指定啓用哪個 profile
- Maven Profile 可以通過命令行指定使用的 profile,但缺少了 spring profile 的一 些特定功能。
在 pom.xml 中定義 Profile
這裏跟上面介紹的一樣,定義兩個/多個 profile 併爲各個 profile 指定自己的屬性:
<profiles>
<profile>
<id>dev</id><!-- 開發環境 -->
<properties>
<active.target.profile>dev</active.target.profile>
</properties>
</profile>
<profile>
<id>test</id><!-- 測試環境 -->
<properties>
<active.target.profile>test</active.target.profile>
</properties>
</profile>
<profile>
<id>prod_test</id><!-- 生測環境 -->
<properties>
<active.target.profile>prod_test</active.target.profile>
</properties>
</profile>
<profile>
<id>prod</id><!-- 生產環境 -->
<properties>
<active.target.profile>prod</active.target.profile>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
</profiles>
在 pom.xml 中定義資源過濾
目的是爲了讓 maven 在構建時用 profile 中指定的屬性來替換 application.properties
中的內容。
<resources>
<resource>
<directory>src/main/resources</directory>
<!--1 先排除所有的profile文件 -->
<excludes>
<exclude>application*.properties</exclude>
<!--
<exclude>application*.yml</exclude>
-->
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<!--2 按需複製所有需的profile文件-->
<filtering>true</filtering>
<includes>
<include>application.properties</include>
<include>application-${spring.profiles.active}.properties</include>
<!--
<include>application.yml</include>
<include>application-${spring.profiles.active}.yml</include>
-->
</includes>
</resource>
</resources>
1位置中,我們通過 excludes
來將所有的 application*.properties(application*.yml)
排除在外,這樣 maven 在打包時就不會複製這些文件。畢竟我們不希望把 application-dev.properties
也包含在 prod 的 jar 包裏。
2位置中,通過開啓 filtering
,maven 會將文件中的 #XX#
替換 profile 中定義的 XX
變量/屬性。另外,我們還通過 includes
來告訴 maven 根據profile 來複制對應的 propertie(yml)
文件。
用 Maven 變量指定 Spring Profile
在 application.properties
文件中加入下面這行:
# 多環境配置文件激活屬性
spring.profiles.active=#active.target.profile#
這裏 active.target.profile
是在 maven profile 中的 properties
定義的,而 #XX#
的語法則是上節提到的 maven filtering 替換變量的語法。
構建不同的包
mvn clean package -P<profile_name>
5、成果展現
此你可以在你的Ide開發環境之中運行,及可以看見很方便的切換當前啓動的環境。爲了顯示當前運行環境,寫了一個controller方法返回當前運行環境
@RestController
public class HelloController {
@Autowired
private Environment env;
@RequestMapping("/hello")
public String index() {
return "Hello World";
}
@RequestMapping("/getCurrentEnv")
public String getCurrentEnv(){
String[] actProfile = env.getActiveProfiles();
String curProfile = actProfile[0];
return curProfile;
}
}
IDE之中運行後如下圖所示:
使用打包工具打包後啓動一下試一試(本次選擇test環境了):
此時此目錄下只有兩個所需的.propertie文件啦
再看看打包後的jar文件之中
訪問一下當前的頁面
到此已經實現指定切換多環境下打包對應的環境,同時也不用在運行微服務時候指定環境啦。
示例源碼所在地址:https://github.com/jianxia612/StudySampleJava/tree/master/Chapter-Muti-Profiles
6、總結
Maven profile 與 Spring profile 有自的優點,結合起來的步驟如下:
- 在
pom.xml
中定義多個 profile 及自己的屬性 - 在
pom.xml
中定義 resource filtering,一方面控制 jar 中包含的資源文件, 一方面允許@XX@
的變量替換 - 在
application.properties
中指定spring.profiles.active
,值爲 maven profile 中定義的屬性。 - 構建時使用
mvn clean package -P<profile>
來指定 profile。 - 如果你不想使用@服務作爲過濾器符號,你可以自定義一個 需要在pom裏面配置即可如下
<properties>
<!-- delimiter that doesn't clash with Spring ${} placeholders -->
<!--
<resource.delimiter>#</resource.delimiter>
-->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
注意:問此還實現了基於yaml文件的過濾,示例工程之中放開對應的yaml文件,然後註釋掉properties
文件即可。另外需要把yaml文件目錄之中文件複製到resources下即可。
7、參考文章
Maven Profile 與 Spring Profile 管理多環境打包