SpringBoot基础篇配置信息之多环境配置信息
前面一篇主要介绍的是如何获取配置信息,接下来则是另外一个非常非常基础和必要的知识点了,应用如何根据不同的环境来选择对应的配置,即配置的多环境选择问题
<!-- more -->
I. 多环境配置
配置区分环境,最直观的如测试环境和生产环境的DB不同,测试环境的应用要求连接测试DB;生成环境的应用要求连生成DB;对于应用本身来说,业务代码啥的都是一样,无非就是DB的配置不同,如果在代码中写死环境判断,然后进行选择配置话,就不太优雅了;
SpringBoot本身就支持多环境配置文件,应用的配置,除了 application.yml
文件之外,还会有环境相关的配置,如下一个实例
application.yml
application-dev.yml
application-pro.yml
1. 多环境选择
a. 命令规则
配置文件,一般要求是以 application
开头,可以是yml文件也可以是properties文件
b. 配置选择
如何确定哪个配置配置文件(application-dev.yml 与 application-pro.yml)生效呢?
- 通过配置信息
spring.profile.active
来指定需要加载的配置文件
通常这个配置信息会放在 applicatin.yml
文件中,如下
spring:
profiles:
active: dev
上面这个表示,当前的配置信息,会从 application.yml
和 application-dev.yml
文件中获取;且-dev
文件中定义的配置信息,会覆盖前面的配置信息
注意
- 上面这个配置的value,可以指定多个配置文件,用英文逗号分隔
- 其中最右边的优先级最高,覆盖左边配置文件中重名的配置信息
c. 实例演示
配置文件内容如下
application.yml
# 端口号
server:
port: 8081
spring:
profiles:
active: dev,biz
biz:
total: application
application-dev.yml
biz:
env: dev-environment
profile: dev-profile
application-pro.yml
biz:
env: pro-environment
profile: pro-profile
application-biz.yml
biz:
whitelist: a,b,c,d,e,f,g
ratelimit: 1,2,3
total: application-biz
profile: biz-profile
通过前面的规则进行分析,当前选中生效的配置文件为
- application.yml, application-dev.yml, application-biz.yml
- 优先级为:biz文件的配置覆盖dev文件,dev文件的覆盖
application
的配置
代码验证如下
package com.git.hui.boot.properties;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.env.Environment;
/**
* Created by @author yihui in 09:17 18/9/20.
*/
@SpringBootApplication
public class Application {
public Application(Environment environment) {
String env = environment.getProperty("biz.env");
String whitelist = environment.getProperty("biz.whitelist");
String ratelimit = environment.getProperty("biz.ratelimit");
String total = environment.getProperty("biz.total");
String profile = environment.getProperty("biz.profile");
// application.yml文件中的配置 spring.profile.active指定具体选中的配置文件,为 application-dev 和 application-biz
// read from application-dev.yml
System.out.println("env: " + env);
// read from application-biz.yml
System.out.println("whitelist: " + whitelist);
System.out.println("ratelimit: " + ratelimit);
// 当配置文件 application.yml, application-dev.yml, application-biz.yml 三个文件都存在时,覆盖规则为
// biz > dev > application.yml (其中 biz>dev的原则是根据 spring.profile.active 中定义的顺序来的,最右边的优先级最高)
// read from application-biz.yml
System.out.println("total: " + total);
// read from application-biz.yml
System.out.println("profile: " + profile);
}
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
输出结果为
env: dev-environment
whitelist: a,b,c,d,e,f,g
ratelimit: 1,2,3
total: application-biz
profile: biz-profile
2. 优先级问题
上面虽然看是实现了多环境的配置问题,但看完之后有一个明显的疑问,选择环境的配置信息写死在application.yml
文件中,难道说部署到测试和生产环境时,还得记得手动改这个配置的值么?
如果是这样的话,也太容易出问题了吧。。。
那么如何解决这个问题呢,常见的一种方式是通过启动脚本,传入当前环境的参数,来覆盖选中的环境
a. 配置文件优先级
默认的配置文件是放在 src/main/resources
目录下,当然也是可以放其他位置的
- 外置,在相对于应用程序运行目录的
/config
子目录中 - 外置,在应用程序运行的目录中
- 内置,放在config包下(即 src/main/resources/config)目录下
- 内置,放在classpath根目录下(即默认的 src/main/resources/目录下)
上面的优先级是从高到低来的,即外置的改与内置的;config下面的高于根目录下的
以内置的两个进行对比,实测结果如下
b. 配置信息来源
前面一篇中,遗留了一个问题,就是在配置文件中配置了属性 user.name = 一灰灰blog
, 但是实际取出的却是 user
(我个人的电脑用户名),也就是说,Environment中读取的配置信息,不仅仅是从配置文件中获取,还要其他的一些配置信息来源
根据优先级对属性来源进行排序,如下
- 根目录下的开发工具全局设置属性(当开发工具激活时为~/.spring-boot-devtools.properties)。
- 测试中的@TestPropertySource注解。
- 测试中的@SpringBootTest#properties注解特性。
- 命令行参数
- SPRING_APPLICATION_JSON中的属性(环境变量或系统属性中的内联JSON嵌入)。
- ServletConfig初始化参数。
- ServletContext初始化参数。
- java:comp/env里的JNDI属性
- JVM系统属性
- 操作系统环境变量
- 随机生成的带random.* 前缀的属性(在设置其他属性时,可以应用他们,比如${random.long})
- 应用程序以外的application.properties或者appliaction.yml文件
- 打包在应用程序内的application.properties或者appliaction.yml文件
- 通过@PropertySource标注的属性源
- 默认属性(通过SpringApplication.setDefaultProperties指定).
3. 环境选择的几种方式
看了上面的配置信息来源,我们可以如何优雅的实现不同环境选择不同的配置文件呢?有下面两个容易想到和实现的方式了
- 命令行参数
- 应用程序外的配置文件
a. 命令行参数方式
这种实现思路就是在启动脚本中,传入当前环境,然后覆盖掉属性 --spring.profiles.active
,对业务来说,就不需要做任何的改动了,只要启动脚本本身区分环境即可,唯一的要求就是遵循统一的规范,一个简单的实现如下
假定命令行的第一个参数就是环境,取出这个参数,传入即可
public static void main(String[] args) {
if (args.length > 0) {
SpringApplication.run(Application.class, "--spring.profiles.active=" + args[0] + ",biz");
} else {
SpringApplication.run(Application.class);
}
}
实测结果,注意下面红框内的pro,覆盖了配置文件中的dev
说明
当然可以直接传入完整的命令行参数--spring.profiles.active=pro,biz
,这样代码内部就不需要进行特殊处理
b. 外置配置文件方式
当程序以独立的jar运行时,我个人的感觉是外置的配置文件是优于内置的配置文件的;因为修改配置的话,不需要重新打包部署,直接改即可
这种实现方式也没啥好多说的,相当于把配置文件拉出来放在外面而已,再根据环境写具体的spring.profiles.active
的值
II. 小结
- SpringBoot是支持多环境的配置,通过配置属性
spring.profiles.active
来指定 -
spring.profiles.active
参数指定多个配置文件时,右边的优于左边的 - 应用外的配置文件优先于应用内,config目录下的优先于根目录下的
- 配置参数来源及优先级可以参看前文: 配置信息来源
- 命令行参数传入时,请注意写法形同
--key=value
III. 其他
0. 项目
1. 一灰灰Blog
- 一灰灰Blog个人博客 https://blog.hhui.top
- 一灰灰Blog-Spring专题博客 http://spring.hhui.top
一灰灰的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛
2. 声明
尽信书则不如,已上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现bug或者有更好的建议,欢迎批评指正,不吝感激
- 微博地址: 小灰灰Blog
- QQ: 一灰灰/3302797840
3. 扫描关注
一灰灰blog
知识星球
- Metaball(元球)效果学习
- ASP.NET MVC 4 RC的JS/CSS打包压缩功能
- 表格可在线编辑效果
- CSS侧边栏宽度不动(更改页面宽度时),内容区宽度自适应
- JS网页顶部弹出可关闭广告图层
- 未来会不会出现人类大脑与人工智能进行链接,而产生的超级大脑?
- android布局文件中android:icon="?attr/menuIconCamera"找不到对应图标路径
- 无限级分类(非递归算法/存储过程版/GUID主键)完整数据库示例_(1)表结构
- Centos7修改默认网卡名(改为eth0)以及网卡启动报错RTNETLINK answers: File exists处理
- 通过企业分布式缓存共享运行时数据
- 移植SlidingMenu Android library,和安装example出现的问题解决
- 无限级分类(非递归算法/存储过程版/GUID主键)完整数据库示例_(2)插入记录
- Centos中yum方式安装java
- 微信小程序新革命催生新物种新物种带来大红利!玩转行业新玩法
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 如何从xml文件创建R语言数据框dataframe
- R语言POT超阈值模型和极值理论EVT分析
- R语言使用灰色关联分析(Grey Relation Analysis,GRA)中国经济社会发展指标
- R语言中的模拟过程和离散化:泊松过程和维纳过程
- R语言Lee-Carter模型对年死亡率建模预测预期寿命
- R语言有极值(EVT)依赖结构的马尔可夫链(MC)对洪水极值分析
- RxSwift 封装 CoreBluetooth(一) 配置
- Golang 操作Excel文件
- 腾讯云TKE-搭建prometheus监控(一)
- Android开发中ProgressDialog简单用法示例
- Android实现拍照及图片裁剪(6.0以上权限处理及7.0以上文件管理)
- Android仿微信调用第三方地图应用导航(高德、百度、腾讯)
- Android数据共享 sharedPreferences 的使用方法
- Android NavigationBar问题处理的方法
- mac系统下载、安装、使用Java8教程