Spring Boot配置文件优先级全解析:如何优雅覆盖默认配置?

📚 一、为什么需要了解配置文件优先级?

想象一下,你正在玩一个游戏🎮,游戏里有默认设置,但你可以通过不同的方式修改这些设置:

  1. 游戏内置的默认设置(就像Spring Boot的默认配置)
  2. 全局配置文件(就像游戏的设置菜单)
  3. 特定场景的特殊设置(就像某个关卡的特殊规则)

Spring Boot的配置文件也是这样层层叠加的!理解它们的优先级,你就能像游戏高手一样精准控制应用的行为了!😎

🎯 二、Spring Boot配置文件全家福

Spring Boot支持多种格式的配置文件,主要有:

  1. .properties文件(传统格式)

    server.port=8080
    
  2. .yml.yaml文件(更简洁的格式)

    server:port: 8080
    
  3. 环境变量

  4. 命令行参数

这些配置可以同时存在,那Spring Boot怎么决定用哪个呢?这就是优先级的奥秘啦!🔍

🏆 三、配置文件优先级完整排行榜

来啦来啦!最关键的优先级排行榜!从高到低依次是:

  1. 命令行参数 👑王者级别

    java -jar myapp.jar --server.port=9090
    
  2. 来自java:comp/env的JNDI属性 (不太常用)

  3. Java系统属性(System.getProperties())

    java -Dserver.port=9090 -jar myapp.jar
    
  4. 操作系统环境变量 💻

    export SERVER_PORT=9090
    
  5. 仅在打包的jar外部的特定profile的应用配置文件

    • application-{profile}.propertiesapplication-{profile}.yml
    • 放在jar包同目录下的config子目录中
  6. 仅在打包的jar外部的特定profile的应用配置文件

    • 直接放在jar包同目录下
  7. 打包在jar内的特定profile的应用配置文件

    • 也就是resources目录下的application-{profile}.propertiesyml
  8. 打包的jar外部的应用配置文件

    • application.propertiesapplication.yml
    • 放在jar包同目录下的config子目录中
  9. 打包的jar外部的应用配置文件

    • 直接放在jar包同目录下
  10. 打包在jar内的应用配置文件

    • 也就是resources目录下的application.propertiesyml
  11. @Configuration类上的@PropertySource注解 🏷️

    @PropertySource("classpath:custom.properties")
    
  12. SpringApplication.setDefaultProperties设置的默认属性

哇!是不是有点多?别担心,我们慢慢来分解理解~ 😊

🧩 四、实际应用场景解析

场景1:开发环境 vs 生产环境

假设我们有一个数据库配置:

  1. 默认配置 (application.yml)

    spring:datasource:url: jdbc:mysql://localhost:3306/dev_dbusername: dev_userpassword: dev_pass
    
  2. 生产环境配置 (application-prod.yml)

    spring:datasource:url: jdbc:mysql://prod-server:3306/prod_dbusername: prod_userpassword: ${DB_PASSWORD}  # 从环境变量获取
    

启动时使用:

java -jar app.jar --spring.profiles.active=prod

这样,生产环境就会自动使用生产配置啦!🎉

场景2:临时覆盖配置

有时候我们需要临时修改某个配置,比如端口号:

java -jar app.jar --server.port=9090

这样命令行参数会覆盖所有文件中的配置,超级方便!✨

🔍 五、深度解析:属性覆盖机制

Spring Boot使用一个叫PropertySource的抽象概念来管理这些配置。当需要获取一个属性值时,它会按照优先级顺序查找,找到第一个匹配的就停止。

举个🌰:

  1. 假设在application.yml中:

    server:port: 8080
    
  2. 同时在环境变量中设置了:

    export SERVER_PORT=9090
    
  3. 启动命令:

    java -jar app.jar --server.port=7070
    

最终端口会是哪个呢?没错,是7070!因为命令行参数优先级最高!🏆

🛠️ 六、如何正确覆盖配置:最佳实践

1. 多环境配置

推荐使用profile机制:

# application.yml
spring:profiles:active: dev  # 默认使用dev环境# application-dev.yml (开发环境)
server:port: 8080# application-prod.yml (生产环境)
server:port: 80

启动时指定profile:

java -jar app.jar --spring.profiles.active=prod

2. 敏感信息处理

千万不要把密码等敏感信息直接写在配置文件中!🙅‍♂️

推荐做法:

spring:datasource:password: ${DB_PASSWORD}

然后通过环境变量设置:

export DB_PASSWORD=mysecretpassword

3. 外部化配置

把配置文件放在jar包外面,方便修改:

.
├── app.jar
├── config
│   └── application.yml
└── application.yml

这样修改配置不需要重新打包!👍

💡 七、高级技巧:自定义属性源

如果你想玩点高级的,可以实现自己的PropertySource

public class CustomPropertySource extends PropertySource {public CustomPropertySource() {super("customPropertySource");}@Overridepublic Object getProperty(String name) {if ("custom.property".equals(name)) {return "我是自定义属性值";}return null;}
}

然后在配置类中注册:

@Configuration
public class AppConfig {@Autowiredprivate ConfigurableEnvironment env;@PostConstructpublic void init() {env.getPropertySources().addAfter(StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,new CustomPropertySource());}
}

这样你就可以用@Value("${custom.property}")获取自定义属性啦!🎩✨

🧪 八、调试技巧:查看实际生效的配置

想知道最终生效的配置是什么?有几种方法:

  1. Actuator端点 (如果引入了actuator)

    http://localhost:8080/actuator/env
    
  2. 启动时打印
    application.yml中添加:

    logging:level:org.springframework.boot.context.properties: DEBUG
    
  3. 编程方式获取

    @Autowired
    private Environment env;public void someMethod() {String port = env.getProperty("server.port");System.out.println("实际端口: " + port);
    }
    

🚨 九、常见问题与解决方案

Q1: 我的配置修改了为什么不生效?

A: 按照以下步骤检查:

  1. 确认修改的文件在优先级更高的位置
  2. 检查是否有拼写错误
  3. 确认没有更高优先级的配置覆盖了它
  4. 检查profile是否激活正确

Q2: yml和properties文件哪个优先级高?

A: 如果同名,.properties优先级高于.yml。但最好统一使用一种格式。

Q3: 如何禁用某个配置文件的加载?

A: 使用:

java -jar app.jar --spring.config.location=optional:file:/path/to/config/

Q4: 配置属性名中的横线(-)和下划线(_)有什么区别?

A: Spring Boot会自动将my.property-namemy.property_name视为相同属性,方便使用。

🌈 十、实战演练:完整示例

让我们通过一个完整例子巩固所学:

  1. 项目结构

    src/main/resources/application.yml          # 默认配置application-dev.yml      # 开发环境application-prod.yml     # 生产环境
    target/myapp.jar
    config/application.yml              # 外部覆盖配置
    
  2. application.yml

    spring:profiles:active: dev
    app:name: MyAppversion: 1.0.0
    
  3. application-dev.yml

    server:port: 8080
    db:url: jdbc:mysql://localhost:3306/dev
    
  4. application-prod.yml

    server:port: 80
    db:url: jdbc:mysql://prod-server:3306/prod
    
  5. config/application.yml (外部配置)

    app:version: 1.0.1  # 覆盖版本号
    
  6. 启动命令

    java -jar myapp.jar --spring.profiles.active=prod --server.port=9090
    
  7. 最终生效的配置

    • server.port: 9090 (命令行参数最高)
    • app.name: MyApp (默认配置)
    • app.version: 1.0.1 (外部配置覆盖)
    • db.url: jdbc:mysql://prod-server:3306/prod (prod profile)

完美!现在你完全掌握了配置覆盖的艺术!🎨

📝 十一、总结:配置优先级核心要点

让我们用一张表格总结关键点:

优先级配置来源示例适用场景
最高命令行参数--server.port=9090临时测试、运维调整
环境变量export SERVER_PORT=9090容器部署、敏感信息
外部配置文件/config/application.yml生产环境配置
jar内配置文件resources/application.yml默认配置、开发环境
最低默认属性SpringApplication.setDefaultProperties框架默认值

记住这个口诀:“命环外jar默认”(命令行>环境变量>外部文件>jar内文件>默认)!🗣️

🎁 十二、Bonus:Spring Boot 2.4+配置新特性

如果你使用Spring Boot 2.4及以上版本,还有一些新玩法:

  1. 配置文件分组

    spring:profiles:group:production: db,redis
    

    启动production相当于同时激活db和redis profile

  2. 导入额外配置

    spring:config:import: optional:file:/path/to/config/
    
  3. 多文档YAML文件
    可以在一个yml文件中用---分隔多个profile配置

🚀 十三、举一反三:其他相关知识点

理解了配置优先级,这些相关概念也更容易掌握:

  1. @Value注解:直接从环境获取属性值

    @Value("${server.port}")
    private int port;
    
  2. @ConfigurationProperties:类型安全的配置绑定

    @ConfigurationProperties(prefix = "app")
    public class AppProperties {private String name;private String version;// getters/setters
    }
    
  3. Spring Cloud Config:集中式配置管理

📖 十四、延伸阅读推荐

想更深入学习的同学可以参考:

  1. Spring Boot官方文档 - 外部化配置
  2. 《Spring Boot实战》 - 第3章 自定义配置
  3. 《Spring微服务实战》 - 配置管理章节

🎉 十五、结语

恭喜你!🎊 现在你已经完全掌握了Spring Boot配置文件优先级的精髓!记住:

  • 理解优先级层次是关键 🔑
  • 合理使用profile管理多环境 🌎
  • 敏感信息用环境变量保护 🔒
  • 外部化配置让运维更灵活 🛠️

如果有任何问题,欢迎在评论区留言讨论哦!😊 我们下次再见!👋

Happy Coding! 💻✨

推荐阅读文章

  • 由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)

  • 如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系

  • HTTP、HTTPS、Cookie 和 Session 之间的关系

  • 什么是 Cookie?简单介绍与使用方法

  • 什么是 Session?如何应用?

  • 使用 Spring 框架构建 MVC 应用程序:初学者教程

  • 有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误

  • 如何理解应用 Java 多线程与并发编程?

  • 把握Java泛型的艺术:协变、逆变与不可变性一网打尽

  • Java Spring 中常用的 @PostConstruct 注解使用总结

  • 如何理解线程安全这个概念?

  • 理解 Java 桥接方法

  • Spring 整合嵌入式 Tomcat 容器

  • Tomcat 如何加载 SpringMVC 组件

  • “在什么情况下类需要实现 Serializable,什么情况下又不需要(一)?”

  • “避免序列化灾难:掌握实现 Serializable 的真相!(二)”

  • 如何自定义一个自己的 Spring Boot Starter 组件(从入门到实践)

  • 解密 Redis:如何通过 IO 多路复用征服高并发挑战!

  • 线程 vs 虚拟线程:深入理解及区别

  • 深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别

  • 10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!

  • “打破重复代码的魔咒:使用 Function 接口在 Java 8 中实现优雅重构!”

  • Java 中消除 If-else 技巧总结

  • 线程池的核心参数配置(仅供参考)

  • 【人工智能】聊聊Transformer,深度学习的一股清流(13)

  • Java 枚举的几个常用技巧,你可以试着用用

  • 由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)

  • 如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系

  • HTTP、HTTPS、Cookie 和 Session 之间的关系

  • 使用 Spring 框架构建 MVC 应用程序:初学者教程

  • 有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误

  • Java Spring 中常用的 @PostConstruct 注解使用总结

  • 线程 vs 虚拟线程:深入理解及区别

  • 深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别

  • 10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!

  • 探索 Lombok 的 @Builder 和 @SuperBuilder:避坑指南(一)

  • 为什么用了 @Builder 反而报错?深入理解 Lombok 的“暗坑”与解决方案(二)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/901958.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

汽车行驶工况特征参数:从“速度曲线”到“驾驶DNA”的硬核解码

作为新能源汽车行业的从业者,你是否曾困惑于这些问题: 为什么同一款电动车,不同用户的实际续航差异高达30%?如何精准量化驾驶行为对电池寿命的影响?车企标定的“NEDC续航”与真实路况差距的根源是什么? 这…

HTTP 2.0 协议特性详解

1. 使用二进制协议,简化传输的复杂性,提高了效率 2. 支持一个 TCP 链接发起多请求,移除 pipeline HTTP/2 移除了 HTTP/1.1中的管道化(pipeline)机制,转而采用多路复用(Multiplexing&#xff0…

完美解决浏览器不能复制的问题(比如赛氪网的中题库练习题)

仅供复制题库题目进行打印学习使用! 最近想把赛氪网题库中的题目打印出来做练习,发现题库中的题目不能复制,不能在试卷上勾画标记太难受了,而且不能留作材料以后复习,故出此策。 而且CtrlP打印出的pdf会缺少题目。(我…

std::set (C++)

std::set 1. 概述定义特点 2. 内部实现3. 性能特征4. 常用 API5. 使用示例6. 自定义比较器7. 注意事项与优化8. 使用建议 1. 概述 定义 template<class Key,class Compare std::less<Key>,class Allocator std::allocator<Key> > class std::set;特点 有…

SSM省市区三级联动和三表联查附带数据库

SSM省市区三级联动和三表联查 ------附带数据库码云地址&#xff1a;https://gitee.com/Mr_ZKC/NO1 数据库在项目中

曲棍球·棒球1号位

中国女子曲棍球队曾涌现过马弋博、李红侠等优秀选手&#xff0c;但“李红”这一名字可能为信息误差。以下为您系统介绍曲棍球&#xff0c;并结合棒球进行对比分析&#xff1a; 曲棍球&#xff08;Hockey&#xff09;核心特点 运动形式 分为草地曲棍球&#xff08;夏季奥运会项…

12芯束装光纤不同包层线颜色之间的排列顺序

为什么光纤线必须按照以下颜色顺序进行排序&#xff1f;这其实是为了防止光污染的问题&#xff0c;不同颜色在传递光时从包层表皮漏光传感到梳妆的其它纤芯上&#xff0c;会有光污染的问题&#xff0c;而为了减少并防止光污染的现象&#xff0c;所以在光通信之中&#xff0c;需…

c++程序的打包编译cmake+make

c打包编译 1 在不用系统中打包介绍1.1 linux中打包c程序的2种方式1.2 windows中打包c程序1.3 cmakeNinja和cmakemake的两种方式对比1.3.1 Ninja是什么&#xff08;可以认为是make工具的一个替代产品&#xff09;1.3.2 cmakeNinja可以用于linux和windows系统中&#xff0c;编译效…

Spark on K8s 在 vivo 大数据平台的混部实战与优化

一、Spark on K8s 简介 (一)定义与架构 Spark on K8s 是一种将 Spark 运行在 Kubernetes(K8s)集群上的架构,由 K8s 直接创建 Driver 和 Executor 的 Pod 来运行 Spark 作业。其架构如下。 Driver Pod:相当于 Spark 集群中的 Driver,负责作业的调度和管理,它会根据作业…

MDA测量数据查看器【内含工具和源码地址】

一、工具介绍 MDA测量数据查看器用于显示和分析以MDF格式提供的测量数据。 支持MDF3.3之前含MDF3.3的二进制格式&#xff0c;支持Vector CANape and ETAS Inca. Kvaser CAN Logger (MDF 3.2) 文件。 MDF (Measurement Data Format)是一种二进制文件&#xff0c;用来记录、交换…

番外篇 | SEAM-YOLO:引入SEAM系列注意力机制,提升遮挡小目标的检测性能

前言:Hello大家好,我是小哥谈。SEAM(Squeeze-and-Excitation Attention Module)系列注意力机制是一种高效的特征增强方法,特别适合处理遮挡和小目标检测问题。该机制通过建模通道间关系来自适应地重新校准通道特征响应。在遮挡小目标检测中的应用优势包括:1)通道注意力增强…

使用VHDL语言实现TXT文件的读写操作

使用FPGA进行图像处理时&#xff0c;通常需要将TXT文件中的图像数据读出到TestBench中&#xff0c;并将仿真的结果写入到TXT文件中&#xff0c;用于确认图像处理的结果是否正确。 VHDL中TXT文件的读写操作如下所示&#xff0c; --------------------------------------------…

基于Redis的4种延时队列实现方式

延时队列是一种特殊的消息队列&#xff0c;它允许消息在指定的时间后被消费。在微服务架构、电商系统和任务调度场景中&#xff0c;延时队列扮演着关键角色。例如&#xff0c;订单超时自动取消、定时提醒、延时支付等都依赖延时队列实现。 Redis作为高性能的内存数据库&#x…

GN ninja 工程化构建例程

文章目录 1. 前言✨2. 工程实例🚩2.1 工程目录结构2.2 工程顶层.gn文件2.3 工具链配置.gn文件2.4 编译配置.gn文件2.5 编译目标配置.gn文件2.6 工程接口文件2.7 动态库编译.gn文件2.8 动态库源文件2.9 静态库编译.gn文件2.10 静态库源文件2.11 主程序编译.gn文件2.12 主程序源…

基于亚博K210开发板——内存卡读写文件

开发板 亚博K210开发板 实验目的 本实验主要学习 K210 通过 SPI 读写内存卡文件的功能 实验准备 实验元件 开发板自带的 TF 卡、LCD 显示屏 &#xff08;提前准备好 FAT32 格式的TF 卡。TF 插入 TF 卡槽的时候注意方向&#xff0c;TF 卡的金手指那一面需要面向开发板&am…

51单片机实验五:A/D和D/A转换

一、实验环境与实验器材 环境&#xff1a;Keli&#xff0c;STC-ISP烧写软件,Proteus. 器材&#xff1a;TX-1C单片机&#xff08;STC89C52RC&#xff09;、电脑。 二、 实验内容及实验步骤 1.A/D转换 概念&#xff1a;模数转换是将连续的模拟信号转换为离散的数字信…

C++ 常用的智能指针

C 智能指针 一、智能指针类型概览 C 标准库提供以下智能指针&#xff08;需包含头文件 <memory>&#xff09;&#xff1a; unique_ptr&#xff1a;独占所有权&#xff0c;不可复制&#xff0c; 可移动shared_ptr&#xff1a;共享所有权&#xff0c;用于引用计数weak_pt…

6.8.最小生成树

一.复习&#xff1a; 1.生成树&#xff1a; 对于一个连通的无向图&#xff0c;假设图中有n个顶点&#xff0c;如果能找到一个符合以下要求的子图&#xff1a; 子图中包含图中所有的顶点&#xff0c;同时各个顶点保持连通&#xff0c; 而且子图的边的数量只有n-1条&#xff0…

Spring Boot 集成金蝶 API 演示

✨ Spring Boot 集成金蝶 API 演示&#xff1a;登录 / 注销 Cookie 保存 本文将通过 Spring Boot 完整实现一套金蝶接口集成模型&#xff0c;包括&#xff1a; ✅ 普通登录✅ AppSecret 登录✅ 注销✅ Cookie 保存与复用 &#x1f4c5; 项目结构 src/ ├── controller/ │…