歡迎存取我的GitHub
這裡分類和彙總了欣宸的全部原創(含配套原始碼):https://github.com/zq2599/blog_demos
本篇概覽
- 本文是《quarkus實戰》系列的第八篇,經過前面的學習,咱們對設定有了足夠了解,但問題也隨之而來:如何讓應用以最小的改動同時執行在不同環境(如本地、測試、生產等)
- 舉個例子,下面是個簡化版組態檔,有兩個設定項,第一個固定不變,第二個隨環境變化各不相同:
# 這個設定資訊在各個環境中都是相同的
greeting.message=hello
# 這個設定資訊在各個環境中都不一樣
quarkus.http.port=9090
- 在實際部署的時候,如何達到要求呢?quarkus.http.port的值隨著環境變化
- 不同環境用不同組態檔是一種方法,但會導致組態檔數量上升,並且greeting.message在各環境都是一樣的,這就出現了冗餘,除了維護成本增加,在管理過程中容易出錯
- 除了多個組態檔,還有種方法可以滿足要求,並且不需要多個組態檔,這就是今天要聊的profile
演示程式碼
- 建立一個demo工程,參考下面的命令,這樣的工程會自帶一個web服務類HobbyResource.java
mvn "io.quarkus:quarkus-maven-plugin:create" \
-DprojectGroupId="com.bolingcavalry" \
-DprojectArtifactId="hello-quarkus" \
-DprojectVersion="1.0-SNAPSHOT" \
-DclassName="HobbyResource" \
-Dpath="actions"
- 用下面這段程式碼來演示設定是否生效,可見用了一個設定項greeting.message,所以我們需要設定它的值才行
package com.bolingcavalry;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.time.LocalDateTime;
@Path("/actions")
public class HobbyResource {
@ConfigProperty(name = "greeting.message")
String message;
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "Hello RESTEasy, " + LocalDateTime.now() + " [" + message + "]";
}
}
- 組態檔是hello-quarkus/src/main/resources/application.properties
# 這個設定資訊在各個環境中都是相同的
greeting.message=hello
設定profile
- profile自己是個普通的設定項,例如在application.properties檔案中,是這樣設定profile的
# 這個設定資訊在各個環境中都是相同的
quarkus.profile=dev
# 如果不指定profile,就使用此設定
quarkus.http.port=8080
- 也可以在System properties中設定,如下所示,如此以來,不同環境只有啟動命令不同,組態檔可以完全不用修改:
java -Dquarkus.profile="dev" -jar hello-quarkus-1.0-SNAPSHOT-runner.jar
同一個設定項在不同profile時的值
- profile的格式是%{profile-name}.config.name
- 以剛才的設定為例,quarkus.http.port設定項共出現三次,前兩次帶有字首,格式是百分號+profile名稱+點號,如下所示
# 指定當前profile
quarkus.profile=dev
# 這個設定資訊在各個環境中都是相同的
greeting.message=hello
# 如果profile為dev,就是用此設定
%dev.quarkus.http.port=8081
# 如果profile為production,就是用此設定
%production.quarkus.http.port=8082
# 如果不指定profile,或者profile既不是dev也不是production,就使用此設定
quarkus.http.port=8080
- 使用上述設定後,因為profile等於dev,會使用不同設定項%dev.quarkus.http.port,也就是說伺服器埠是8081,另外兩個設定%production.quarkus.http.port和quarkus.http.port都無效
- 啟動應用驗證,我這是用mvn quarkus:dev命令啟動的,如下圖紅框:
- 瀏覽器存取地址http://localhost:8081/actions,服務正常,設定項greeting.message的值也符合預期:
- 再試試另一種設定,先在application.properties檔案中刪除設定項quarkus.profile=dev,再改用mvn quarkus:dev -Dquarkus.profile=production啟動應用,這次生效的設定項是%production.quarkus.http.port,如下圖:
- 存取地址也變成了http://localhost:8082/actions
需要大寫的場景
- 在《quarkus實戰之六:設定》一文中,曾提到過設定方式有六種,有幾種要求設定項大寫,例如在.env中的設定,此時格式變成了_{PROFILE}_CONFIG_KEY=value,舉例如下
# 這個設定資訊在各個環境中都是相同的
GREETING_MESSAGE=hello
# 如果profile為dev,就是用此設定
_DEV_QUARKUS_HTTP_PORT=8081
# 如果profile為production,就是用此設定
_PRODUCTION_QUARKUS_HTTP_PORT=8082
# 如果不指定profile,就使用此設定
QUARKUS_HTTP_PORT=8080
- 注意,實測發現在.env中設定QUARKUS_PROFILE=dev無效,也就是說不能在.env中指定profile,此時應該在啟動命令中指定profile,例如:
java -Dquarkus.profile=dev -jar hello-quarkus-1.0-SNAPSHOT-runner.jar
不指定profile時的預設值
- 不指定profile的時候,quarkus會給profile設定預設值,有三種可能:dev、test、prod,具體邏輯如下:
- 如果啟動命令是mvn quarkus:dev,profile等於dev,如下圖,大家應該見過多次了:
- 單元測試期間,例如執行命令mvn test,profile等於test
- 以上兩種場景之外,profile等於prod,例如用命令java -jar hello-quarkus-1.0-SNAPSHOT-runner.jar啟動應用
每個profile對應一個組態檔
- 如果您希望每個profile都有自己的組態檔,quarkus也支援,如下所示,src/main/resources/目錄下同時存在兩個組態檔:application.properties和application-staging.properties
resources
├── META-INF
│ └── resources
│ └── index.html
├── application-staging.properties
└── application.properties
- application.properties內容如下
greeting.message=hello
quarkus.http.port=8080
- application-staging.properties內容如下
greeting.message=hello
quarkus.http.port=8081
- 如果啟動命令指定了profile,如mvn quarkus:dev -Dquarkus.profile=staging,此時只有application-staging.properties檔案生效,如下圖
- 還要注意一點:此時如果指定一個不存在的profile,例如mvn quarkus:dev -Dquarkus.profile=xxxxxxx,此時生效的是application.properties檔案生效,如下圖
Parent Profile
- parent profile解決的問題是:假設當前profile是aaa,那麼設定項xxx對應的設定名應該是%dev.aaa,如果找不到%dev.aaa,就去找它的parent profile對應的設定項,來看個例子就清楚了,假設設定資訊如下:
# 指定profile的名字
quarkus.profile=dev
# 指定parent的名字
quarkus.config.profile.parent=common
%common.quarkus.http.port=9090
%dev.quarkus.http.ssl-port=9443
quarkus.http.port=8080
quarkus.http.ssl-port=8443
- 當前profile已經指定為dev
- parent profile已經指定為common
- 對於設定項quarkus.http.port,由於沒找到%dev.quarkus.http.port,就去找parent profile的設定,於是找到了%common.quarkus.http.port,所以值為9090
- 對於設定項quarkus.http.ssl-port,由於找到了%dev.quarkus.http.ssl-port,所以值為9443
- 對於設定項quarkus.http.port,如果%dev.quarkus.http.port和%common.quarkus.http.port都不存在,會用quarkus.http.port,值為8080
修改預設profile
- 前面曾說到,啟動的時候如果不指定profile,quarkus會指定預設的profile:將應用製作成jar,以java -jar命令啟動時,profile會被設定為prod
- 如果您想讓預設值從prod變為其他值,可以在構建的時候用-Dquarkus.profile去改變它,例如下面這個命令,jar包生成後,啟動的時候預設profile是prod-aws
mvn clean package -U -Dquarkus.package.type=uber-jar -Dquarkus.profile=prod-aws
- 啟動jar的時候不指定profile,如下圖,profile已被設定為prod-aws
三個關鍵注意事項(重要)
- 應用在執行時,只會有一種profile生效
- 如果想在程式碼獲取當前的profile,可以用此API
io.quarkus.runtime.configuration.ProfileManager#getActiveProfile
- 用註解的方式獲取profile是無效的,下面這段程式碼無法得到當前的profile
@ConfigProperty("quarkus.profile")
String profile;
歡迎關注部落格園:程式設計師欣宸
學習路上,你不孤單,欣宸原創一路相伴...