需求说明
开发过程中,经常出现的环境必定会有以下几个:开发环境、测试环境、预发布环境(可能会有,可能没有)、正式环境;由于这些环境的存在,我们就不得不去维护这一系列环境的配置(如数据库连接、商户资料等等)及版本,那么要如何去管理这些配置呢?
常用的方式
-
第一种:版本管理工具
比如,通过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; } }
-
application.yml ;用于配置公共的配置项,即各个环境都需要,且配置都相同的项;
-
运行时环境自定
#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); } }
OtherConfig 对象@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; }
@Data public class OtherConfig { private String okey1; private String okey2; }
- 准备一个用于测试的接口
@RestController public class BusiController { @Autowired BusiConfig busiConfig; @GetMapping("busiconf") public BusiConfig busiConfig(){ return busiConfig; } }
- yml-config.yml;公共配置,所有环境都存在且值相同的配置文件
-
效果测试
- 切换测试环境
-
切换正式环境
- 切换测试环境
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 .
- 运行镜像
运行容器时通过指定(spring.profiles.active)进行运行时环境切换#docker run -p 端口映射 --name=容器别名 镜像名:版本 --spring.profiles.active=运行环境 docker run -p 8080:8080 --name=myconfig myconfig:1.0.0 --spring.profiles.active=dev
到此! 运行时配置文件自动切换即可完成!