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

需求说明

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

常用的方式

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

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

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

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容