前提

这篇文章是《SpringBoot2.x入门》专辑的「第4篇」文章,使用的SpringBoot版本为2.3.1.RELEASEJDK版本为1.8

主要介绍SpringBoot配置文件一些常用属性、配置文件的加载优先级以及一些和配置相关的注意事项。

关于SpringBoot的配置文件

一个基于标准的引入了SpringBoot组件的Maven项目的结构一般如下:

Root(项目根目录)  - src   - main    - java    - resources  #   - target     pom.xml

资源文件存放在src/main/resouces目录下,而配置文件本质上也是资源文件,所以「项目内的」配置文件就存放于该目录下。从SpringBoot的属性源加载器PropertySourceLoader的实现来看,目前支持PropertiesYaml两种配置文件类型。两者各有优势:Yaml的配置属性更灵活,而Properties的配置不容易出错(笔者前公司的技术规范中明确了SpringBoot应用必须使用Properties配置文件,因为运维或者开发同事曾因为生产配置使用了Yaml格式的文件,编辑期间因为空格问题导致了严重的生产故障)。下文会使用Properties配置文件作为示例。

SpringBoot的配置文件使用了profile(profile本身就有剖面、配置文件的含义,下面会把profile作为一个专有名词使用)的概念,可以类比为区分不同环境的标识符,一个SpringBoot应用允许使用多个profile,所以配置文件的格式必须为application-${profile}.文件后缀,例如:

src/main/resources   - application.properties   - application-dev.properties  #    - application-test.properties # 

其中不带profile标识的application.properties,可以理解为「主配置文件」,也就是SpringBoot的配置文件其实有继承关系,项目启动时,主配置文件无论如何都会优先加载,然后被激活的profile标识的配置文件才会加载,可以通过属性spring.profiles.active指定激活哪一个profile配置文件,如:

# 指定加载application-dev.propertiesspring.profiles.active=dev

# 或者同时加载application-dev.properties和application-test.propertiesspring.profiles.active=dev,test

spring.profiles.active一般可以在主配置文件application.properties中指定,获取通过启动命令参数指定(java -jar -Dspring.profiles.active=prod app.jar或者java -jar app.jar --spring.profiles.active=prod)。

可以通过自动装配org.springframework.core.env.Environment,通过Environment#getActiveProfiles()获取当前激活的profile数组,例如:

import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.CommandLineRunner;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.core.env.Environment;import java.util.Arrays;

@Slf4j@SpringBootApplicationpublic class Ch2Application implements CommandLineRunner {

    @Autowired    private Environment environment;

    public static void main(String[] args) {        SpringApplication.run(Ch2Application.class, args);    }

    @Override    public void run(String... args) throws Exception {        log.info("Active profiles:{}", Arrays.toString(environment.getActiveProfiles()));    }}

运行结果如下:


这里用到了CommandLineRunner接口作为展示,后面的文章会介绍该接口的使用方式。

常用的基本配置属性

一般情况下会引入spring-boot-starter-web开发web项目,有几个基本配置笔者认为是必须的。主配置文件application.properties中应该标识应用名和默认选用的profile,例如API网关的主配置文件如下:

spring.application.name=api-gatewayspring.profiles.active=dev

此外,主配置中间中应该配置一些不容易变动的属性,例如MybatisMapper扫描路径、模板引擎Freemarker的配置属性等等。而profile标识的配置文件中,应该配置一些跟随环境变化的配置或者经常更变的属性,例如MySQL数据源的配置、Redis的连接配置等等,以便通过spring.profiles.active直接切换不同环境的中间件连接属性或者第三方配置。在Hello World类型的项目中,一般添加server.port指定容器的启动端口,如application-dev.properties的内容如下:

server.port=8081

配置文件加载优先级与属性覆盖

除了主配置文件会优先profile标识的配置文件加载之外,SpringBoot还支持通过文件系统加载配置文件,这些配置文件不一定在项目内(准确来说是项目编译之后打出来的包内),还可以存在于特定的磁盘路径中。这一点可以参考SpringBoot官方文档2.Externalized Configuration一节:


默认的配置文件加载优先级顺序是:

  1. file:./config/(项目部署包所在目录的同级config目录下的application-[profile].[properties,yaml]文件)
  2. file:./config/*/(项目部署包所在目录的同级config目录下的任意子目录中的application-[profile].[properties,yaml]文件)
  3. file:./(项目部署包所在目录的application-[profile].[properties,yaml]文件)
  4. classpath:/config/(项目部署包内类路径下的config目录下的application-[profile].[properties,yaml]文件)
  5. classpath:/(项目部署包内类路径下的application-[profile].[properties,yaml]文件)

「眼尖的伙伴可能会发现,在项目中的resources目录下添加的配置文件的加载优先级是最低的(打包后相当于第5条)」。可以通过spring.config.location属性覆盖上面的顺序,如spring.config.location=classpath:/,classpath:/config/,一般不建议改变默认的配置顺序,除非有特殊的使用场景。

另外,还可以通过spring.config.additional-location属性指定额外附加的搜索配置文件的路径,并且「优先级比默认的配置顺序要高」,假如只配置了spring.config.additional-location=classpath:/custom-config/,file:./custom-config/,那么配置文件加载优先级顺序是:

  1. file:./custom-config/(项目部署包所在目录的同级custom-config目录下的application-[profile].[properties,yaml]文件)
  2. classpath:custom-config/(项目部署包内类路径下的custom-config目录下的application-[profile].[properties,yaml]文件)
  3. file:./config/(项目部署包所在目录的同级config目录下的application-[profile].[properties,yaml]文件)
  4. file:./config/*/(项目部署包所在目录的同级config目录下的任意子目录中的application-[profile].[properties,yaml]文件)
  5. file:./(项目部署包所在目录的application-[profile].[properties,yaml]文件)
  6. classpath:/config/(项目部署包内类路径下的config目录下的application-[profile].[properties,yaml]文件)
  7. classpath:/(项目部署包内类路径下的application-[profile].[properties,yaml]文件)

基于这个特性,在不对接配置中心的前提下,可以让运维伙伴在生产服务器上先配置好服务所需的生产环境的配置文件:

# 假设这个是生产服务器的文件路径/data/apps/api-gateway     - api-gateway.jar     - config       - application-prod.properties

在编写启动脚本的时候只需指定profileprod即可,应用会读取/data/apps/api-gateway/config/application-prod.properties的属性,这样就能避免生产配置或者敏感属性泄漏给开发人员。

这里还有一个比较重要的问题就是:如果在多种路径下的配置文件定义了同一个属性,那么属性会依照一个优先级顺序进行覆盖。因为SpringBoot除了配置文件,还支持命令行、JNDI属性、系统属性等等,如果全部列举会比较复杂,这里按照目前分析过的内容列举这个优先级顺序:

  1. 命令行中的属性参数。
  2. 项目部署包之外的application-profile.[properties,yaml]文件。
  3. 项目部署包内的application-profile.[properties,yaml]文件。
  4. 项目部署包之外的application.[properties,yaml]文件。
  5. 项目部署包内的application.[properties,yaml]文件。

举个例子,假如启动参数中添加--app.author=throwable,配置文件application.properties中添加属性app.author=throwable-x,而配置文件application-dev.properties中添加属性app.author=throwable-y,那么使用profile=dev启动应用的时候,优先获取到的是属性app.author=throwable


如果看过SpringBoot属性加载的源码可知,其实属性优先级的思路在设计属性加载模块的时候正好相反,所有的配置文件都会进行解析,构成一个复合的PropertySource,后解析的参数总是在顶层,然后获取属性的时候,总是先从顶层获取。

自定义配置属性与IDE亲和性

有时候需要配置自定义属性,会出现在IDE中会无法识别而"标黄"的场景。这个时候可以应用IDE亲和性。在主流的IDEEclipseIntelliJ IDEA中,只需要引入SpringBoot的属性元数据描述文件(spring-configuration-metadata.json或者additional-spring-configuration-metadata.json),即可让IDE识别,提供目录引导跳转的功能,不再"标黄"。具体的做法是在项目的resources/META-INF目录中引入属性元数据描述文件,然后编写属性描述即可:

// resources/META-INF/spring-configuration-metadata.json{  "properties": [    {      "name": "app.author",      "type": "java.lang.String",      "description": "The author of app."    }  ]}

spring-configuration-metadata.json文件的格式可以参考SpringBoot多个starter中已经存在的文件,「完成这一点,代码洁癖患者或者强迫症患者会感觉良好」

小结

这篇文章简单总结了配置文件加载的优先级顺序和配置属性的覆盖优先级顺序,这两点需要完全掌握,可以自行通过一些例子改变一下配置文件进行熟悉。配置属性覆盖的问题很容易导致生产故障,如果掌握了本节的内容,对于SpringBoot配置属性方面的问题应该可以快速定位和解决。代码仓库:

  • Github:https://github.com/zjcscut/spring-boot-guide/tree/master/ch2-profile

(本文完 c-2-d e-a-20200705)

java读取classpath配置文件_SpringBoot2.x入门教程:理解配置文件相关推荐

  1. ROS2入门教程—理解话题(Topic)

    ROS2入门教程-理解话题(Topic) 1 启动小海龟仿真器 2 rqt_graph 3 ros2 topic list 4 ros2 topic echo 5 ros2 topic info 6 ...

  2. java编程输出平行四边形_JAVA语言入门教程之打印图形实例——打印平行四边形...

    本文主要向大家介绍了JAVA语言入门教程之打印图形实例--打印平行四边形,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助. 输出平行四边形: public class Parallelo ...

  3. java语言打印图形_JAVA语言入门教程之打印图形实例——打印矩形

    本文主要向大家介绍了JAVA语言入门教程之打印图形实例--打印矩形,通过具体的内容向大家展示,希望对大家学习JAVA语言有所帮助. 输出矩形: public class Rect { public s ...

  4. 【JAVA】Dozer 介绍及快速入门教程

    文章目录 概述 使用 安装 入门 XML 映射 注解映射 SpringBoot 集成 结语 概述 Dozer 是什么? Dozer 是 Java Bean 到 Java Bean 的映射器,他以递归的 ...

  5. java security 详解_Spring Security入门教程 通俗易懂 超详细 【内含案例】

    Spring Security的简单使用 简介 SSM 整合 Security 是比较麻烦的,虽然Security的功能比 Shiro 强大,相反却没有Shiro的使用量多 SpringBoot出现后 ...

  6. TensorFlow全新的数据读取方式:Dataset API入门教程

    Dataset API是TensorFlow 1.3版本中引入的一个新的模块,主要服务于数据读取,构建输入数据的pipeline. 此前,在TensorFlow中读取数据一般有两种方法: 1.使用pl ...

  7. java中的gui_java gui快速入门教程

    JCheckBox和JRadioButton使用示例 import java.awt.*; import javax.swing.*; class Hobby extends JPanel { JCh ...

  8. flexpaper java 例子_Flexpaper二次开发入门教程》(十) Flexpaper简单使用-第一个Flexpaper例子...

    4. Flexpaper简单使用 通过上面三章的内容,大家对Flexpaper.SWFTools应该有大概的了解了,SWF文件也已经生成了,我们开始进入Flexpaper的使用的介绍. 本章中只演示F ...

  9. java 气泡图_JavaScript图表库Highcharts入门教程(八):气泡图

    Highcharts是一款纯JavaScript编写的图表库,为你的Web网站.Web应用程序提供直观.交互式图表.当前支持折线.曲线.区域.区域曲线图.柱形图.条形图.饼图.散点图.角度测量图.区域 ...

最新文章

  1. HTTP Status 400
  2. Redis整合Spring Data Redis 开发key和value乱码
  3. vb 访问远程计算机,vb 怎么访问远程电脑SQL SERVER数据库
  4. Python 3基础教程32-正则
  5. SDG、SGD-M实现
  6. Linux之grep及正则表达式
  7. mysql 5.6.16 log_mysql-5.6.16装配脚本
  8. 汇编语言实现计算器---可加减乘除括号负数混合运算
  9. LeetCode 301. 删除无效的括号(回溯)
  10. 怎样查看class文件的jdk版本号
  11. 进程篇—进程整理(转)
  12. 自由软件之父Richard Stallman及其思想
  13. 28.earch in Rotated Sorted Array(排序旋转数组中查找)
  14. 交友 它能让霍金有一口伦敦腔,也在帮聋哑人重新开口说话
  15. 用python语言怎么打出菱形的*号_Python打印“菱形”星号代码方法
  16. 如果延迟退休势在必行,区块链如何助力“养老助老”?
  17. SQL的常见函数的使用方法和举例说明
  18. 专业的人做专业的事 VxRail助中通业务创新驶上“快车道”
  19. 单独上线音乐直播APP,“LOOK直播”能给网易云音乐带来什么?
  20. VBA多条件选择及自动填表及计算汇报

热门文章

  1. Notepad2替代系统自带的记事本
  2. Canvas3 汉化QA和BUG反馈
  3. VLAN+DHCP(1)(附抓包)
  4. FLEX是什么及与FLASH的关系的介绍
  5. Handle table中CAS操作与A-B-A Problem解析
  6. html5 drag this,HTML5拖放(drag和drog)
  7. 高职扩招有计算机专业吗,高职扩招计算机专业
  8. springcloud 子项目怎么导入_Spring Cloud基础面试题大集合
  9. java练习:打印 数字1、2、3、4的组合,不能以4开头,1和3不能相邻,且数字不能重复
  10. android studio 前言中不允许有内容_Android Studio 中 System Trace 的新增功能