SpringBoot学习之旅(十一)---运行时环境、配置文件自动切换

需求说明

开发过程中,经常出现的环境必定会有以下几个:开发环境、测试环境、预发布环境(可能会有,可能没有)、正式环境;由于这些环境的存在,我们就不得不去维护这一系列环境的配置(如数据库连接、商户资料等等)及版本,那么要如何去管理这些配置呢?

常用的方式

  • 第一种:版本管理工具
    比如,通过git去维护不同的分支,不同的分支有不同的配置文件信息;发布的时候,切换不同的分布打不同版本的包进行上传发布

    • 缺点
      • 分支众多且复杂;因为不同的版本存在不同的分支,因此在分支的维护耗时大大增加
      • 配置文件混乱;因为使用的是同一个配置文件,只不过是通过不同的分支,维护着同一个配置文件中的不同配置项
  • 第二种:通过SpringBoot的配置不同环境的配置文件,运行时进行切换
    通过配置多个环境的配置文件,运行时通过环境(spring.profiles.active)切换,实现不通配置文件的切换,
    推荐使用该做法,同时以下将详细介绍该方法的实现方式及使用方式;能大大提高代码的维护性及版本的可控制性

    • 缺点
      • 容易遗漏;由于不同的环境是使用的不同的配置,因此,可能出现开发环境做了修改,但是测试环境、正式环境忘记调整了,从而导致本地运行正常,发布之后不正常的问题;这个算问题也不算问题,思维清晰缜密是一个程序员的基本素养。
  • 第三种:通过SpringBoot Config进行配置文件管理
    其实他和第二种的差别不算大,也都是通过当前运行的不同环境(spring.profiles.active),进行配置文件的切换,只不过是这些配置文件都是通过git进行管理维护,可以实现一些权限的控制,自动刷新配置等高级操作;

    • 缺点
      • 使用的复杂度相对较高;可以参考SpringBoot学习之旅(九)---超详细的自动刷新配置教程;
      • 单独的SpringBoot无法使用;至少得配合Eureka和git来使用。

源码

下载地址

项目级配置

  • 配置文件说明
    SpringBoot项目通常都是通过application.yml进行当前项目的配置,如数据库、redis、mq、编码等等的配置项;那么当环境变化的时候,如何去更换不通的配置参数呢?如:不同环境的数据库配置;那么我们就将配置文件分为一下四个(注意: 这里文件名必须使用application开头):

    • application.yml ;用于配置公共的配置项,即各个环境都需要,且配置都相同的项;
      server:
        port: 8080 #设置项目的端口
      spring:
        profiles:
          active: local #设置项目运行的环境
      
    • application-local.yml ;用于配置本地环境的配置项
      conf: 本地
      
    • application-dev.yml ;用于配置测试环境的配置项
      conf: 测试
      
    • application-pro.yml ;用于配置正式环境的配置项
      conf: 正式
      
    • 编写一个接口用于测试当前运行的环境下conf的值
      @RestController
      public class ConfController {
              @Value("${conf}")
              public String conf;
      
              @GetMapping("conf")
              public String getConf() {
                      return conf;
              }
      }
      
  • 运行时环境自定

    #java -jar jar文件地址 --spring.profiles.active=环境别名
    java -jar target/myconfig.jar --spring.profiles.active=pro
    
  • 测试效果

    • 切换测试环境



    • 切换正式环境



    这样同一个版本包即可实现各个环境的切换

自定义配置

业务开发过程中,除了项目的一些基础配置之外,不可避免的会存在一些自定义的业务流程配置;同样也就不可避免的会存在不同环境下的配置文件,以下即演示自定义配置文件的动态切换;

  • 配置文件说明

    • yml-config.yml;公共配置,所有环境都存在且值相同的配置文件
      busi:
          key: va-all
      
    • yml-config-local.yml;本地开发环境配置文件
      busi:
          key1: va1-local
          key2: va2-local
          key3:
              keyc1: vac1-local
          key4:
              okey1: ova1-local
              okey2: ova2-local
          key5: 9,10
      
    • yml-config-dev.yml;测试环境配置文件
      busi:
          key1: va1-dev
          key2: va2-dev
          key3:
              keyc1: vac1-dev
          key4:
              okey1: ova1-dev
              okey2: ova2-dev
          key5: 6,7,8
      
    • yml-config-pro.yml;正式环境配置文件
      busi:
          key1: va1-pro
          key2: va2-pro
          key3:
              keyc1: vac1-pro
          key4:
              okey1: ova1-pro
              okey2: ova2-pro
          key5: 1,2,3,4,5
      
    • 配置自动将配置文件注入为对象
      由于上面使用的是yml格式,因此准备一个用于加载yml格式的工厂对象
      public class YamlPropertyLoaderFactory extends DefaultPropertySourceFactory {
              @Override
              public PropertySource createPropertySource(String name, EncodedResource resource) throws IOException {
                      if (resource == null) {
                              return super.createPropertySource(name, resource);
                      }
      
                      return new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource()).get(0);
              }
      }
      
      添加业务配置对象
      @Data
      @Component
      //当前要注入的所有属性的前缀
      @ConfigurationProperties(prefix = "busi")
      //指定要扫描的文件路径,${spring.profiles.active}用于指定当前运行环境的配置文件
      //YamlPropertyLoaderFactory yaml文件加载工厂,默认是使用的propertes加载工厂,如果配置文件后缀是propertes,那么就不用配置factory属性
      @PropertySource(value = {"classpath:myconfig/yml-config.yml","classpath:myconfig/yml-config-${spring.profiles.active}.yml"}, encoding = "UTF-8", factory = YamlPropertyLoaderFactory.class)
      public class BusiConfig {
              private String key;
      
              private String key1;
      
              private String key2;
      
              //以map的形式接受多个子属性
              private Map key3;
      
              //以对象接口多个子属性
              private OtherConfig key4;
      
              //以列表的形式
              private List key5;
      }
      
      OtherConfig 对象
      @Data
      public class OtherConfig {
              private String okey1;
              private String okey2;
      }
      
    • 准备一个用于测试的接口
      @RestController
      public class BusiController {
              @Autowired
              BusiConfig busiConfig;
      
              @GetMapping("busiconf")
              public BusiConfig busiConfig(){
                      return busiConfig;
              }
      }
      
  • 效果测试

    • 切换测试环境

    • 切换正式环境



Docker方式运行

既然是使用的同一个包在运行时通过环境变量进行切换,那么如果使用docker的方式运行的时候,要如何配置来实现一个镜像在运行时进行环境切换呢?

  • 编写DockerFile
    FROM hub.c.163.com/library/java:8-alpine
    
    #指明该镜像的作者
    MAINTAINER lupf XXX
    
    #添加文件
    ADD target/*.jar myconfig.jar
    
    #改镜像监听的端口
    EXPOSE 8080
    
    #指定镜像可以像一个可执行文件一样执行
    ENTRYPOINT ["java","-jar","-Duser.timezone=GMT 8","/myconfig.jar"]
    
  • 构建镜像
    //构建一个镜像名为: myconfig  版本为:1.0.0的镜像
    docker build -t myconfig:1.0.0 .
    
  • 运行镜像
    #docker run -p 端口映射 --name=容器别名 镜像名:版本  --spring.profiles.active=运行环境
    docker run -p 8080:8080 --name=myconfig myconfig:1.0.0 --spring.profiles.active=dev
    
    运行容器时通过指定(spring.profiles.active)进行运行时环境切换

到此! 运行时配置文件自动切换即可完成!

你可能感兴趣的:(SpringBoot学习之旅(十一)---运行时环境、配置文件自动切换)