欢迎访问我的GitHub

这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos

本篇概览

  • 本文是《quarkus实战》系列的第八篇,经过前面的学习,咱们对配置有了足够了解,但问题也随之而来:如何让应用以最小的改动同时运行在不同环境(如本地、测试、生产等)
  • 举个例子,下面是个简化版配置文件,有两个配置项,第一个固定不变,第二个随环境变化各不相同:

    # 这个配置信息在各个环境中都是相同的
    greeting.message=hello
    # 这个配置信息在各个环境中都不一样
    quarkus.http.port=9090
  • 在实际部署的时候,如何达到要求呢?<font color="blue">quarkus.http.port</font>的值随着环境变化
  • 不同环境用不同配置文件是一种方法,但会导致配置文件数量上升,并且<font color="blue">greeting.message</font>在各环境都是一样的,这就出现了冗余,除了维护成本增加,在管理过程中容易出错
  • 除了多个配置文件,还有种方法可以满足要求,并且不需要多个配置文件,这就是今天要聊的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"
  • 用下面这段代码来演示配置是否生效,可见用了一个配置项<font color="blue">greeting.message</font>,所以我们需要配置它的值才行

    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 + "]";
      }
    }
  • 配置文件是<font color="blue">hello-quarkus/src/main/resources/application.properties</font>

    # 这个配置信息在各个环境中都是相同的
    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的格式是<font color="blue">%{profile-name}.config.name</font>
  • 以刚才的配置为例,<font color="red">quarkus.http.port</font>配置项共出现三次,前两次带有前缀,格式是<font color="blue">百分号+profile名称+点号</font>,如下所示

    # 指定当前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等于<font color="blue">dev</font>,会使用不同配置项<font color="blue">%dev.quarkus.http.port</font>,也就是说服务端口是<font color="red">8081</font>,另外两个配置<font color="blue">%production.quarkus.http.port</font>和<font color="blue">quarkus.http.port</font>都无效
  • 启动应用验证,我这是用<font color="blue">mvn quarkus:dev</font>命令启动的,如下图红框:
    在这里插入图片描述
  • 浏览器访问地址<font color="blue">http://localhost:</font><font color="blue">8081</font><font color="blue">/actions</font>,服务正常,配置项greeting.message的值也符合预期:
    在这里插入图片描述
  • 再试试另一种配置,先在application.properties文件中删除配置项<font color="blue">quarkus.profile=dev</font>,再改用<font color="red">mvn quarkus:dev -Dquarkus.profile=production</font>启动应用,这次生效的配置项是<font color="blue">%production.quarkus.http.port</font>,如下图:
    在这里插入图片描述
  • 访问地址也变成了<font color="blue">http://localhost:</font><font color="blue">8082</font><font color="blue">/actions</font>
    在这里插入图片描述

需要大写的场景

  • 《quarkus实战之六:配置》一文中,曾提到过配置方式有六种,有几种要求配置项大写,例如在<font color="blue">.env</font>中的配置,此时格式变成了<font color="red">\_{PROFILE}_CONFIG_KEY=value</font>,举例如下

    # 这个配置信息在各个环境中都是相同的
    GREETING_MESSAGE=hello
    
    # 如果profile为dev,就是用此配置
    _DEV_QUARKUS_HTTP_PORT=8081
    
    # 如果profile为production,就是用此配置
    _PRODUCTION_QUARKUS_HTTP_PORT=8082
    
    # 如果不指定profile,就使用此配置
    QUARKUS_HTTP_PORT=8080
  • 注意,实测发现在.env中配置<font color="blue">QUARKUS_PROFILE=dev</font>无效,也就是说不能在.env中指定profile,此时应该在启动命令中指定profile,例如:

    java -Dquarkus.profile=dev -jar hello-quarkus-1.0-SNAPSHOT-runner.jar

    不指定profile时的默认值

  • 不指定profile的时候,quarkus会给profile设置默认值,有三种可能:dev、test、prod,具体逻辑如下:
  • 如果启动命令是<font color="blue">mvn quarkus:dev</font>,profile等于<font color="red">dev</font>,如下图,大家应该见过多次了:
    在这里插入图片描述
  • 单元测试期间,例如执行命令<font color="blue">mvn test</font>,profile等于<font color="red">test</font>
    在这里插入图片描述
  • 以上两种场景之外,profile等于<font color="red">prod</font>,例如用命令<font color="blue">java -jar hello-quarkus-1.0-SNAPSHOT-runner.jar</font>启动应用
    在这里插入图片描述

每个profile对应一个配置文件

  • 如果您希望每个profile都有自己的配置文件,quarkus也支持,如下所示,<font color="blue">src/main/resources/</font>目录下同时存在两个配置文件:<font color="red">application.properties</font>和<font color="red">application-staging.properties</font>
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,如<font color="blue">mvn quarkus:dev -Dquarkus.profile=staging</font>,此时只有<font color="red">application-staging.properties</font>文件生效,如下图

image-20220309081432688

  • 还要注意一点:此时如果指定一个不存在的profile,例如<font color="blue">mvn quarkus:dev -Dquarkus.profile=xxxxxxx</font>,此时生效的是<font color="red">application.properties</font>文件生效,如下图

image-20220309081901953

Parent Profile

  • parent profile解决的问题是:假设当前profile是aaa,那么配置项xxx对应的配置名应该是<font color="blue">%dev.aaa</font>,如果找不到<font color="blue">%dev.aaa</font>,就去找它的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
  1. 当前profile已经指定为dev
  2. parent profile已经指定为common
  3. 对于配置项<font color="blue">quarkus.http.port</font>,由于没找到<font color="red">%dev.quarkus.http.port</font>,就去找parent profile的配置,于是找到了<font color="red">%common.quarkus.http.port</font>,所以值为<font color="blue">9090</font>
  4. 对于配置项<font color="blue">quarkus.http.ssl-port</font>,由于找到了<font color="red">%dev.quarkus.http.ssl-port</font>,所以值为<font color="blue">9443</font>
  5. 对于配置项<font color="blue">quarkus.http.port</font>,如果<font color="red">%dev.quarkus.http.port</font>和<font color="red">%common.quarkus.http.port</font>都不存在,会用<font color="red">quarkus.http.port</font>,值为<font color="blue">8080</font>

修改默认profile

  • 前面曾说到,启动的时候如果不指定profile,quarkus会指定默认的profile:将应用制作成jar,以<font color="blue">java -jar</font>命令启动时,profile会被设置为<font color="red">prod</font>
  • 如果您想让默认值从prod变为其他值,可以在构建的时候用<font color="blue">-Dquarkus.profile</font>去改变它,例如下面这个命令,jar包生成后,启动的时候默认profile是<font color="red">prod-aws</font>
mvn clean package -U -Dquarkus.package.type=uber-jar -Dquarkus.profile=prod-aws
  • 启动jar的时候不指定profile,如下图,profile已被设定为<font color="blue">prod-aws</font>

image-20220309085425879

三个关键注意事项(重要)

  • quarkus官方给出了三个重点注意事项
  • 应用在运行时,只会有一种profile生效
  • 如果想在代码获取当前的profile,可以用此API

    io.quarkus.runtime.configuration.ProfileManager#getActiveProfile
  • 用注解的方式获取profile是<font color="red">无效的</font>,下面这段代码无法得到当前的profile

     @ConfigProperty("quarkus.profile")
     String profile;

欢迎关注思否:程序员欣宸

学习路上,你不孤单,欣宸原创一路相伴...

程序员欣宸
147 声望24 粉丝

热爱Java和Docker