前言:在之前的开发环境中要跟改配置,测试环境也要改,每次切换环境都要手动修改配置文件
常常发生"我们在本地能运行,怎么部署到服务器就报错"的情况,一不小心就把测试环境的配置提交到代码库。因此我们提出了多环境开发配置。
多环境开发配置:
在SpringBoot中,多环境配置的管理核心是利用Profile机制,它允许我们为不同的运行环境(开发,测试,生产)定义独立的配置,并在应用启动时动态的激活,从而实现配置等隔离与灵活切换。
核心实现方式:Profile 特定配置文件
总之就是为每个环境创建独立的配置文件,根据实际需求进行修改。
|------------------------------------------------|
| application.yml:公共配置文件,存放所有环境通用的配置 。 |
| application-dev.yml :开发环境(dev)的专属配置。 |
| application-test.yml :测试环境(test)的专属配置。 |
| application-prod.yml :生产环境(prod)的专属配置 |
事例:
# 公共配置,可以设置一个默认激活的Profile,比如开发环境
spring:
profiles:
active: dev
application:
name: my-spring-boot-app
# 其他公共配置...
# 开发环境特定配置
server:
port: 8081
spring:
datasource:
url: jdbc:mysql://localhost:3306/dev_db?useSSL=false
username: dev_user
password: dev_password
jpa:
hibernate:
ddl-auto: update
show-sql: true
logging:
level:
root: DEBUG
配置文件的加载机制:
++启动应用 → 读取spring.profiles.active → 加载匹配的环境配置文件++
SpringBoot是如何根据环境来匹配对应的配置呢,底层核心机制是Spring Boot是通过**ConfigFileApplicationListener** 和**PropertySourceLoader** 来实现这个功能的。总之,Spring Boot通过文件名匹配 + 配置合并 + 优先级覆盖 的机制,实现了环境与配置的自动对应。
// Spring Boot源码中的关键组件
public class ConfigFileApplicationListener {
// 配置文件加载器
private Set<String> getSearchLocations() {
Set<String> locations = new LinkedHashSet<>();
// 默认扫描位置:classpath:/, classpath:/config/, file:./, file:./config/
locations.add("classpath:/");
locations.add("file:./");
return locations;
}
// 构建要加载的文件名
private List<String> getFilenames(Profile profile) {
List<String> names = new ArrayList<>();
names.add("application"); // 基础文件名
if (profile != null) {
names.add("application-" + profile); // 环境特定文件名
}
return names;
}
}
设计思想:
| 特性 | 说明 |
|---|---|
| 约定优于配置 | Spring Boot通过命名规则自动发现配置,无需手动声明 |
| 覆盖机制 | 环境特定配置覆盖基础配置,优先级更高 |
| 继承关系 | 环境配置只定义差异项,减少重复 |
| 外部化配置 | 可以通过命令行/环境变量动态指定使用哪个环境 |
而当我们把项目的jar包打包给前端人员是,我们在主配置类中一般是默认一个环境,而当前端人员需要其他的环境时,还需要我们后端人员修改默认配置,然后再打包给前端吗,当然不用这么麻烦,这就是下面我们要学习的多环境命令行启动。
多环境命令行启动:
指定环境:
# 开发环境
java -jar tlias-web-management-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev
# 测试环境
java -jar tlias-web-management-0.0.1-SNAPSHOT.jar --spring.profiles.active=test
# 生产环境
java -jar tlias-web-management-0.0.1-SNAPSHOT.jar --spring.profiles.active=prod
指定环境+接口:
# 开发环境,使用8081端口
java -jar myapp.jar --spring.profiles.active=dev --server.port=8081
# 生产环境,使用80端口
java -jar myapp.jar --spring.profiles.active=prod --server.port=80
指定环境+数据库连接:
# 临时覆盖数据库连接
java -jar myapp.jar --spring.profiles.active=dev \
--spring.datasource.url=jdbc:mysql://localhost:3306/testdb \
--spring.datasource.username=testuser \
--spring.datasource.password=testpass
注意点:当执行maven生命周期的时候,先执行clean,之后再进行打包,同时要在设置中把字符集设置成UTF-8,防止乱码。
Spring Boot 配置优先级(从高到低)
-
命令行参数(最高)
-
JVM 系统参数(-D参数)
-
环境变量
-
配置文件(application.yml)
-
默认值(最低)
原理:
Spring Boot多环境命令行参数的原理可以概括为:
-
解析阶段 :Spring Boot通过
SimpleCommandLineArgsParser解析--key=value格式的参数 -
存储阶段 :将解析后的参数封装成
CommandLinePropertySource,作为最高优先级的属性源 -
合并阶段:将所有属性源(命令行、环境变量、配置文件等)按优先级组成链表
-
读取阶段 :
PropertyResolver按优先级顺序查找属性值,返回第一个找到的值 -
应用阶段 :通过
@Value、@ConfigurationProperties等方式将属性注入到Bean中
这就是为什么命令行参数能够覆盖配置文件中的设置,并且能够动态指定环境的原因
Maven与SpringBoot多环境兼容问题:
首先我们先区分一下这两个多环境开发:
Maven多环境开发
形象的说,Maven的多环境开发就相当于是在建造不同的房子,不同的环境就是不同的建筑队,
# 好比是:
- 开发环境 → 请"快装公司"(快速施工,能随时改)
- 测试环境 → 请"标准公司"(按规范施工)
- 生产环境 → 请"精装公司"(精细施工,质量第一)
✅ 带不同的工具(依赖包)
✅ 用不同的材料(资源文件)
✅ 按不同的标准(插件配置)
✅ 干完活就走(构建完成就结束
这些打包之后是不同的jar包
SpringBoot的多环境开发:
是同一套房子的不同居住方式
- 开发模式 → 白天办公用(开大灯、开电脑、放工作音乐)
- 休闲模式 → 晚上休息用(开小夜灯、放轻音乐)
- 聚会模式 → 周末party用(开彩灯、放嗨曲、开空调)
-
✅ 开不同的灯(不同端口)
-
✅ 放不同的音乐(不同日志级别)
-
✅ 用不同的电器(不同数据源)
-
✅ 随时切换模式(运行时改参数
这些打包之后是同一个jar包。
这时我们就会有疑问,为什么这两个看似毫不相干的工作,会产生兼容问题呢。简单的说,当我们建造的是普通简单的房子时,而SpringBoot却要按照豪华型房子居住,未免有点强人所难。实际上的兼容问题就是++配置的重复定义,资源过滤冲突,多环境组合混乱。++
兼容的解决方案(多环境组合混乱):
mvn clean package -Pdev # Maven的dev
java -jar app.jar --spring.profiles.active=test # Spring的test
# 结果:Maven用dev配置打包,Spring用test配置运行,完全不匹配
Maven中设置多环境属性
<profiles><profile>
<id>dev_env</id><properties>
<profile.active>dev</profile.active></properties><activation><activeByDefault>true</activeByDefault></activation></profile><profile>
<id>pro_env</id><properties><profile.active>pro</profile.active></properties>
</profile><profile>
<id>test_env</id><properties><profile.active>test</profile.active></properties>
</profile></profiles>
SpringBoot中引用Maven属性
spring:profiles:
active: ${profile.active}占位符,解析占位符,加载Maven的属性
spring:
profiles:proserver:
port:80spring:
profiles:devserver:
port:81
spring:profiles: testserver:
port:82
对资源文件开启对默认占位符的解析
<build><plugins><plugin>
<artifactId>maven-resources-plugin</artifactId><configuration>
<encoding>utf-8</encoding>
<useDefaultDelimiters>true</useDefaultDelimiters>
</configuration></plugin></plugins></build>
这里的资源插件的作用是把pom.xml文件中的值传到配置文件,而不是Spring的占位符需要资源插件,Spring占位符的解析是Spring框架自带的功能
| 方面 | maven-resources-plugin | Spring PropertyResolver |
|---|---|---|
| 所属 | Maven插件 | Spring框架核心 |
| 处理对象 | @...@ |
${...} |
| 处理时机 | 编译时 | 运行时 |
| 配置位置 | pom.xml | application.yml |
| 必须配置吗 | 不是必须的 | 自动集成,无需配置 |
| 依赖 | 需要显式声明 | Spring Boot自带 |
配置文件分类
SpringBoot中4级配置文件
1级: file : config/application.yml
【最高】
2级: file :application.yml
3级: classpath: config/application.yml
4级: classpath: application.yml
【最低】
作用:
1级与2级留做系统打包后设置通用属性
3级与4级用于系统开发阶段设置通用属性
结语:
最后的最后,感谢大家观看到最后,如果对你有帮助,请**一键三连,点赞,关注(拜托了),收藏,**你的支持就是我最大的鼓励,持续更新对你有帮助的知识!
