SpringBoot多环境配置踩坑指南

 更新时间:2026年03月26日 08:32:20   作者:神奇小汤圆  
这篇文章主要为大家详细介绍了SpringBoot多环境配置的相关方法和避坑指南,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下

先说说我的项目情况

我目前维护的项目用的是 Spring Boot 2.5.15,配置文件的组织方式是这样的:

resources/config/dev/hbase.properties
resources/config/dev/zk.properties
resources/config/dev/hbase.xml
resources/config/prod/hbase.properties
resources/config/prod/zk.properties
resources/config/prod/hbase.xml

代码里也是五花八门:有用 @Value 注入的,有用 @ConfigurationProperties 的,还有硬编码用 ClassLoader.getResourceAsStream() 读取的。说实话,这种”历史遗留”代码,懂的都懂。

最近研究配置加载方式的时候,发现门道还挺多。今天就结合自己的理解,把这几个常用参数彻底掰扯清楚。

一、-Xbootclasspath/a:JVM 级别的”后门”

这玩意儿到底干嘛的?

简单来说,这是 JVM 的标准参数,用来在 Bootstrap ClassLoader 的搜索路径末尾追加额外的类路径。Bootstrap ClassLoader 是 JVM 最顶层的类加载器,负责加载核心类库。

我什么时候用它?

主要是为了解决那种需要从 ClassLoader 直接读取配置文件的场景。比如我项目里那些用 getResourceAsStream("xxx.properties") 的代码,如果不加这个参数,有时候就读不到外部配置文件。

用法示例

# Linux/Mac
java -Xbootclasspath/a:/path/to/config -jar app.jar
# Windows(注意用分号)
java -Xbootclasspath/a:C:\path\to\config -jar app.jar

踩坑提醒

  • 路径分隔符:Linux 用 :,Windows 用 ;,搞错了直接报错
  • 会改变 ClassLoader 的加载顺序,有时候会引起一些诡异的类加载问题

二、-Dloader.path:Spring Boot 可执行 Jar 的专属武器

原理是啥?

这个参数是 Spring Boot 的 LaunchedURLClassLoader 专门识别的。当你打包成 Fat Jar 后,Spring Boot 会用自己定制的 ClassLoader 来加载类,而这个参数就是告诉它:”嘿,除了这些,再去这些地方找找”。

我能用它干嘛?

  • 加载外部的配置文件
  • 动态添加额外的 jar 包
  • 实现某种程度上的”热更新”(虽然不建议在生产环境这么玩)

用法示例

# Linux/Mac
java -Dloader.path=/path/to/config,/path/to/lib -jar app.jar
# Windows
java -Dloader.path=C:\path\to\config;C:\path\to\lib -jar app.jar

实际应用场景

我现在的启动脚本就是这样写的:

java -Dloader.path=/opt/myapp/config \
     -Dspring.profiles.active=prod \
     -jar myapp.jar

这样配置文件就可以放在 jar 包外面,改配置不用重新打包,运维同学也很开心。

三、spring.config.location:彻底接管配置加载

注意!这是”替换”不是”追加”

这个参数会完全覆盖 Spring Boot 默认的配置文件搜索位置。默认情况下,Spring Boot 会按这个顺序找配置:

  • file:./config/
  • file:./
  • classpath:/config/
  • classpath:/

一旦你用了 spring.config.location,上面这些位置就都被忽略了,只加载你指定的位置。

三种设置方式

# 1. 命令行参数(优先级最高)
java -jar app.jar --spring.config.location=/path/to/config/
# 2. 系统属性
java -Dspring.config.location=/path/to/config/ -jar app.jar
# 3. 环境变量
export SPRING_CONFIG_LOCATION=/path/to/config/

我的建议

除非你有特殊需求,否则不要轻易用这个参数。一旦用了,默认的配置加载逻辑就全被 干掉了,很容易踩坑。

四、spring.config.additional-location:更友好的”追加”方式

和上面的区别

这个参数是追加而不是替换。它会在默认配置位置的基础上,额外增加你指定的搜索路径。

优先级顺序

  • spring.config.location 指定的位置(最高)
  • spring.config.additional-location 指定的位置
  • 默认位置(最低)

这是我目前最推荐的方式

java -jar app.jar --spring.config.additional-location=/opt/myapp/config/

这样既保留了 Spring Boot 的默认行为,又能加载外部的配置文件,两全其美。

五、配置加载优先级:一定要搞清楚

Spring Boot 的配置属性优先级从高到低:

  • 命令行参数--server.port=8080
  • Java 系统属性System.getProperties()
  • 操作系统环境变量
  • RandomValuePropertySource${random.*}
  • Jar 包外部的 profile 配置文件
  • Jar 包内部的 profile 配置文件
  • Jar 包外部的 application.properties
  • Jar 包内部的 application.properties
  • @PropertySource 注解加载的配置
  • 默认属性(最低)

记住这个优先级很重要,有时候配置没生效,很可能就是优先级被覆盖了。

六、我的项目改造实录

原来的问题

我项目里有一堆这样的代码:

InputStream is = HbaseConfig.class.getClassLoader()
    .getResourceAsStream("hbase.properties");

这种写法有几个问题:

  • 只能从 classpath 根目录加载
  • 无法加载 config/dev/hbase.properties 这种嵌套路径
  • 不支持 Spring Boot 的配置优先级机制

改造方案

方案一:使用 Spring 的 ResourceLoader(推荐)

@Autowired
private ResourceLoader resourceLoader;
public void loadConfig() throws IOException {
    Resource resource = resourceLoader.getResource(
        "classpath:config/" + env + "/hbase.properties"
    );
    Properties props = new Properties();
    props.load(resource.getInputStream());
}

方案二:直接用 @Value 注入

@Value("classpath:config/${spring.profiles.active}/hbase.properties")
private Resource hbaseConfig;

方案三:彻底拥抱 Spring Boot(最佳)

把配置文件内容合并到 application-dev.yml 和 application-prod.yml 中,完全交给 Spring Boot 管理。

七、各环境的最佳实践

开发环境(IDE 中运行)

项目结构:

project/
├── src/main/resources/
│   ├── application.yml          # 主配置
│   ├── application-dev.yml      # 开发环境
│   ├── application-prod.yml     # 生产环境
│   └── config/
│       ├── dev/
│       └── prod/
└── external-config/             # 外部配置(gitignore)
    └── application-local.yml    # 个人本地配置

IDE 启动参数:

-Dspring.profiles.active=dev
-Dspring.config.additional-location=file:./external-config/

Linux 生产环境

目录结构:

/opt/myapp/
├── app.jar
├── config/
│   ├── application.yml
│   ├── hbase.properties
│   └── zk.properties
└── logs/

启动脚本:

#!/bin/bash
APP_HOME=/opt/myapp
CONFIG_DIR=$APP_HOME/config
LOG_DIR=$APP_HOME/logs
mkdir -p $LOG_DIR
java \
  -Dspring.profiles.active=prod \
  -Dspring.config.additional-location=file:$CONFIG_DIR/ \
  -Dloader.path=$CONFIG_DIR \
  -Xms512m \
  -Xmx1024m \
  -jar $APP_HOME/app.jar \
  >> $LOG_DIR/app.log 2>&1 &
echo $! > $APP_HOME/app.pid

Systemd 服务配置:

[Unit]
Description=My Spring Boot Application
After=syslog.target
[Service]
User=appuser
WorkingDirectory=/opt/myapp
Environment="SPRING_PROFILES_ACTIVE=prod"
Environment="SPRING_CONFIG_ADDITIONAL_LOCATION=file:/opt/myapp/config/"
ExecStart=/usr/bin/java -jar /opt/myapp/app.jar
Restart=on-failure
[Install]
WantedBy=multi-user.target

Windows 生产环境

目录结构:

C:\Apps\MyApp\
├── app.jar
├── config\
│   ├── application.yml
│   ├── hbase.properties
│   └── zk.properties
└── start.bat

启动脚本:

@echo off
setlocal

set APP_HOME=C:\Apps\MyApp
set CONFIG_DIR=%APP_HOME%\config

java ^
  -Dspring.profiles.active=prod ^
  -Dspring.config.additional-location=file:%CONFIG_DIR%/ ^
  -Dloader.path=%CONFIG_DIR% ^
  -Xms512m ^
  -Xmx1024m ^
  -jar %APP_HOME%\app.jar

endlocal

八、最后:我的选择建议

场景推荐参数原因
开发环境spring.config.additional-location保留默认行为,方便调试
生产环境(Linux)spring.config.additional-location + loader.path灵活、可控
生产环境(Windows)spring.config.additional-location + loader.path同上
需要 ClassLoader 读取-Xbootclasspath/a兼容遗留代码
完全自定义配置位置spring.config.location特殊需求专用

最后说一句:不要过度设计。对于大部分项目来说,spring.config.additional-location 配合 spring.profiles.active 已经够用了。除非你真的有特殊需求,否则没必要搞得太复杂。

到此这篇关于SpringBoot多环境配置踩坑指南的文章就介绍到这了,更多相关SpringBoot多环境配置内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 如何导入spring源码到IDEA

    如何导入spring源码到IDEA

    这篇文章主要介绍了如何导入spring源码到IDEA,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • 你真的会使用Java的方法引用吗

    你真的会使用Java的方法引用吗

    这篇文章主要给大家介绍了关于Java方法引用的相关资料,方法引用是Java8的新特性,方法引用其实也离不开Lambda表达式,本文通过示例代码介绍的很详细,需要的朋友可以参考下
    2021-08-08
  • Java基于Spire Cloud Excel把Excel转换成PDF

    Java基于Spire Cloud Excel把Excel转换成PDF

    这篇文章主要介绍了Java基于Spire Cloud Excel把Excel转换成PDF,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-05-05
  • 理解Java多线程之并发编程

    理解Java多线程之并发编程

    这篇文章主要介绍了理解Java多线程之并发编程的相关资料,需要的朋友可以参考下
    2023-02-02
  • Java线程池队列PriorityBlockingQueue原理分析

    Java线程池队列PriorityBlockingQueue原理分析

    这篇文章主要介绍了Java线程池队列PriorityBlockingQueue原理分析,PriorityBlockingQueue队列是 JDK1.5 的时候出来的一个阻塞队列,但是该队列入队的时候是不会阻塞的,永远会加到队尾,需要的朋友可以参考下
    2023-12-12
  • @ConfigurationProperties与EnableConfigurationProperties使用及说明

    @ConfigurationProperties与EnableConfigurationProperties使用及说明

    这段文章详细介绍了@ConfigurationProperties和@enableConfigurationProperties注解在Spring框架中的应用,通过实例展示了如何实现配置文件与实体类属性的注入,并强调了@enableConfigurationProperties注解的正确使用场景和注意事项
    2026-06-06
  • Spring国际化和Validation详解

    Spring国际化和Validation详解

    本文介绍了SpringBoot中国际化和Validation的融合实现,包括配置MessageSource和LocalValidatorFactoryBean,以及自定义约束注解和校验器,通过解析请求头中的Accept-Language,SpringBoot可以返回不同语言的文本信息
    2024-11-11
  • mybatis分页及模糊查询功能实现

    mybatis分页及模糊查询功能实现

    这篇文章主要为大家详细为大家详细介绍了mybatis实现分页及模糊查询功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06
  • Spring事务原理解析

    Spring事务原理解析

    Spring事务有可能会提交,回滚、挂起、恢复,所以Spring事务提供了一种机制,可以让程序员来监听当前Spring事务所处于的状态,这篇文章主要介绍了Spring底层事务原理,需要的朋友可以参考下
    2022-12-12
  • Java中ScheduledExecutorService介绍和使用案例(推荐)

    Java中ScheduledExecutorService介绍和使用案例(推荐)

    ScheduledExecutorService是Java并发包中的接口,用于安排任务在给定延迟后运行或定期执行,它继承自ExecutorService,具有线程池特性,可复用线程,提高效率,本文主要介绍java中的ScheduledExecutorService介绍和使用案例,感兴趣的朋友一起看看吧
    2024-10-10

最新评论