SpringBoot多环境配置实战指南

前言:在之前的开发环境中要跟改配置,测试环境也要改,每次切换环境都要手动修改配置文件

常常发生"我们在本地能运行,怎么部署到服务器就报错"的情况,一不小心就把测试环境的配置提交到代码库。因此我们提出了多环境开发配置。

多环境开发配置:

在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 配置优先级(从高到低)

  1. 命令行参数(最高)

  2. JVM 系统参数(-D参数)

  3. 环境变量

  4. 配置文件(application.yml)

  5. 默认值(最低)

原理:

Spring Boot多环境命令行参数的原理可以概括为:

  1. 解析阶段 :Spring Boot通过SimpleCommandLineArgsParser解析--key=value格式的参数

  2. 存储阶段 :将解析后的参数封装成CommandLinePropertySource,作为最高优先级的属性源

  3. 合并阶段:将所有属性源(命令行、环境变量、配置文件等)按优先级组成链表

  4. 读取阶段PropertyResolver按优先级顺序查找属性值,返回第一个找到的值

  5. 应用阶段 :通过@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级用于系统开发阶段设置通用属性

结语:

最后的最后,感谢大家观看到最后,如果对你有帮助,请**一键三连,点赞,关注(拜托了),收藏,**你的支持就是我最大的鼓励,持续更新对你有帮助的知识!

相关推荐
翊谦1 小时前
Java Agent开发 Milvus 向量数据库安装
java·数据库·milvus
晓晓hh1 小时前
JavaSE学习——迭代器
java·开发语言·学习
Laurence1 小时前
C++ 引入第三方库(一):直接引入源文件
开发语言·c++·第三方库·添加·添加库·添加包·源文件
查古穆2 小时前
栈-有效的括号
java·数据结构·算法
kyriewen112 小时前
你点的“刷新”是假刷新?前端路由的瞒天过海术
开发语言·前端·javascript·ecmascript·html5
Java面试题总结2 小时前
Spring - Bean 生命周期
java·spring·rpc
硅基诗人2 小时前
每日一道面试题 10:synchronized 与 ReentrantLock 的核心区别及生产环境如何选型?
java
014-code2 小时前
String.intern() 到底干了什么
java·开发语言·面试
eastyuxiao2 小时前
如何在不同的机器上运行多个OpenClaw实例?
人工智能·git·架构·github·php
421!2 小时前
GPIO工作原理以及核心
开发语言·单片机·嵌入式硬件·学习