一文学会Spring Boot配置属性
admin
2024-01-21 04:16:53
0

一文学会Spring Boot配置属性

Spring Boot允许将配置外部化,以便在不同的环境中使用相同的程序代码。可以使用各种外部配置源,包括Java属性文件、YAML文件、环境变量、命令行参数。配置属性值可以通过@Value注解直接注入到bean中,或者通过@ConfigurationProperties注解绑定到结构化对象。

Spring Boot中的配置具有顺序性,该顺序允许程序员合理的覆盖属性值,顺序高的配置值可以覆盖顺序低的配置值,优先级从低到高如下

  1. 默认属性 - 可通过 SpringApplication.setDefaultProperties 设置
  2. @Configuration 类上配置的 @PropertySource 注解 - 需要注意在刷新应用上下文context之前,不会将此类属性添加到 Environment 中。对于特殊的场景配置会导致读不到属性值,如 logging.* and spring.main.*
  3. Config Data - 例如 application.properties 文件
  4. 配置随机属性值
  5. 操作系统环境变量
  6. JVM 环境变量 - 如可以通过System.getProperties()获取的属性值
  7. 从 java:comp/env 获取的 JNDI 属性值
  8. ServletConext 初始化参数
  9. ServletConfig 初始化参数
  10. SPRING_APPLICATION_JSON 中的属性值
  11. 命令行启动参数
  12. 测试属性值 - 使用 @SpringBootTest 、测试注解中的属性值
  13. @TestPropertySource 注解
  14. devtools 启用时,Devtools 工具在 $HOME/.config/spring-boot 目录设置的全局属性

配置文件的优先级顺序如下:

  • jar包内部的 application.properties 配置文件
  • profile 属性指定jar包内部的配置文件 - 如application-{profile}.properties
  • jar包外部的 application.properties 配置文件
  • profile 属性指定jar包外部的配置文件 - 如application-{profile}.properties

建议在项目中使用相同格式的配置文件,统一为 .properties 或 .yml 格式。假设在相同的目录中同时存在两种类型的配置文件,.properties优先

@Value

@Component
public class MyBean {@Value("${name}")private String name;}

以上代码使用 @Value注解读取配置文件的name值。可以应用不同的场景:

  • jar包内部 application.properties 中配置的name属性

  • 运行新环境时,jar外部 application.properties 文件中name属性值可以覆盖jar包内部的属性值

  • 测试时,可以通过命令行覆盖属性值

    java -jar app.jar --name="Spring"
    

获取命令行属性值

默认情况下,Spring Boot 可以转化命令中 以 --开头的参数,如 --server.port=9000,并把它们添加到Spring Environment环境中,命令行的参数始终偶先配置文件中的参数。

如果不想将命令行中的属性配置添加到 Environment中,可以通过代码禁用该行为:

SpringApplication.setAddCommandLineProperties(false)

JSON 应用属性

环境变量跟系统属性可能会存在一些属性名称上的冲突,为了解决此类问题。Spring Boot允许将属性代码快编码为单个的JSON结构。启动应用程序时,spring.application.json (SPRING_APPLICATION_JSON) 属性值将被解析并添加到 Environment环境中。

例如,SPRING_APPLICATION_JSON

// 方式一
java -jar target/springboot-study-0.0.1-SNAPSHOT.jar --spring.application.json='{\"name\":\"test\"}'// 方式二
java -jar target/springboot-study-0.0.1-SNAPSHOT.jar -Dspring.application.json='{\"name\":\"test\"}'

外部属性文件

系统启动时,Spring Boot 自动从指定的目录加载 application.propertiesapplication.yaml 配置文件。指定目录(优先级顺序从低到高)如下:

  1. 从 classpath 加载
    • classpath 根目录
    • classpath 下 /config 目录
  2. 从当前目录 加载
    • 当前目录加载
    • 当前目录下的 config 子目录加载
    • config 下的子目录加载

如果不喜欢默认的配置文件名 application,可以通过 spring.config.name 在命令行中指定其他配置文件名称,如下指定 myproject.properties 或 myproject.yaml 文件:

$ java -jar myproject.jar --spring.config.name=myproject

也可以显示指定系统加载的文件,多个目录之间使用逗号进行分隔

$ java -jar myproject.jar --spring.config.location=\optional:classpath:/default.properties,\optional:classpath:/override.properties

大多数情况下,每个spring.config选项关联单个文件或者目录。多个目录之间按照定义顺序进行处理,后面的位置可以覆盖前面位置的值。spring.config.location配置的目录将会替换默认的读取路径。例如 spring.config.location 配置为 “optional:classpath:/custom-config/,optional:file:./custom-config/”,Spring Boot 读取的完整路径为:

  • optional:classpath:custom-config/
  • optional:file:./custom-config/

如果只是新增路径,然不是替换默认路径。可以使用 spring.config.additional-location 配置。从其他位置加载的属性配置将覆盖默认的属性配置。例如 spring.config.additional-location 配置为 optional:classpath:/custom-config/,optional:file:./custom-config/, Spring Boot 将会读取的路径为:

  • optional:classpath:/;optional:classpath:/config/
  • optional:file:./;optional:file:./config/;optional:file:./config/*/
  • optional:classpath:custom-config/`
  • optional:file:./custom-config/

Spring Boot允许你有选择性的覆盖另一个配置中的值。开发人员可以在应用程序中为应用程序提供默认值。然后在运行时指定一个特定的路径位置然后覆盖这些默认值。

Optional Locations

默认情况下,当指定的配置文件路径不存在时,Spring Boot 将会终止启动应用程序,并抛出异常 ConfigDataLocationNotFoundException。

如果你想指定路径,但并不确定该路径是否一直存在,你可以加上 optional: 前缀。spring.config.location 、spring.config.additional-location都可以使用 这个前缀,也可以使用 spring.config.import 声明。例如, spring.config.import 值为 optional:file:./myconfig.properties 允许应用程序启动,及时 myconfig.properties文件不存在。

如果想忽略ConfigDataLocationNotFoundException异常,并继续启动应用,可以使用 spring.config.on-not-found,值设置为 ingore。系统使用SpringApplication.setDefaultProperties(…) 或 system/environment 中的值

Wildcard Locations

如果配置路径中包含 * 号,则它将被视为通配符位置。加载配置文件时会将子目录也考虑进去。例如 需要配置Redis、Mysql配置文件,考虑将这两部分配置文件分开,方便管理。这将导致两个文件

  • /config/redis/application.properties
  • /config/mysql/application.properties

这种情况需要使用通配符进行处理,让Spring Boot识别并加载这两个目录下的文件,如 config/*/。默认情况下,Spring Boot 在默认的搜索位置搜索 config/*/ 目录,jar包外部的 /config 文件夹也会被识别加载。

通配符位置仅适用于外部目录,不能在classpath: 下 使用通配符

Profile Specific Files

Spring Boot 允许使用 application-{profile} 加载不同环境的配置文件。例如,应用程序在 prod 生产环境中启动,则配置文件命名为 application-prod.yml。跟标准的配置文件加载流程类似,特定环境下profile配置文件会覆盖默认的配置文件。

如果多个 profile 文件被指定,默认应用后面的profile文件 (last-wins strategy),如 同时在 prod、live profile配置文件中指定spring.profiles.active属性,application-live.properties 配置文件中的值 覆盖 application-prod.properties.

last-wins strategy应用于目录组级别,即相同的目录组,后面文件的配置属性覆盖前面文件的配置属性。还是使用上面的案例,同时指定 prod、live 配置文件,如下:
/cfgapplication-live.properties
/extapplication-live.propertiesapplication-prod.properties
使用spring.config.location属性,配置值为: classpath:/cfg/,classpath:/ext/,则文件处理顺序如下:
1. /cfg/application-live.properties
2. /ext/application-prod.properties
3. /ext/application-live.properties将 classpath:/cfg/;classpath:/ext/ 使用分号进行分隔时,则/cfg,/ext目录被当成同一个目录级别,则文件处理顺序如下:
1. /ext/application-prod.properties
2. /cfg/application-live.properties
3. /ext/application-live.properties

系统使用默认的profile配置文件,默认值为 [default],即没有显示指定profile配置文件时,则使用 application-default 配置文件。

Importing Additional Data

应用程序可以使用spring.config.import属性从其他目录导入配置文件,导入的文件被当成原配置文件的一部分进行处理,如下:

spring:application:name: "myapp"config:import: "optional:file:./dev.properties"

上述配置将导入当前目录下的dev.properties(如果文件存在)。dev.properties属性文件的值将优先处理,在dev.properties中可以重新定义 spring.application.name的值。

在properties/yaml 单个文件中导入的顺序并不重要,如下两个配置它们的结果是一样的。

spring:config:import: "my.properties"
my:property: "value"
my:property: "value"
spring:config:import: "my.properties"

在上述的两个示例中,mysql.properties中的值将优先于文件中定义的属性值。使用 spring.config.import 导入多个文件时,目录文件按顺序处理,后面导入的文件优先级高。

Importing Extensionless Files

一些云平台需要导入外部文件系统的配置文件,应对这种场景,需要告诉Spring Boot如何加载他们。

假如需要在application.properties 导入 /etc/config/myconfig文件,使用示例如下

spring:config:import: "file:/etc/config/myconfig[.yaml]"

Using Configuration Trees

etc/config/myapp/usernamepassword

假设存在如上目录配置文件,需要同时读取他们的配置属性。当然可以使用 spring.config.import 一个个的导入,但是可以使用以下更直观的方式导入:

spring:config:import: "optional:configtree:/etc/config/"

可以在Environment 环境变量中使用 myapp.username 、myapp.password 配置属性。

如果同一个父目录,存在多个子配置目录,可以使用通配符,减少代码代码量,如下:

etc/config/dbconfig/db/usernamepasswordmqconfig/mq/usernamepassword
spring:config:import: "optional:configtree:/etc/config/*/"

Property Placeholders

application.properties 、applicaiton.yml中的属性值在使用时会经过 Environment处理,因此配置可以关联之前已经定义的值(从系统属性、环境变量中关联)。${name}占位符可以使用在任何位置。属性占位符还可以指定默认值,如 ${name:default}.

app:name: "MyApp"description: "${app.name} is a Spring Boot application written by ${username:Unknown}"

username 可能其他地方没有设置,配置默认值;app.name为设置为 MyApp,因此description的最终结果为:MyApp is a Spring Boot application written by Unknown.

Working With Multi-Document Files

Spring Boot 允许将单个文件拆分程多个文件,每个文件单独添加,文档按从上到下的顺序处理,后面的文件可以覆盖前面文件中定义的属性。YAML支持多文档语法,— 字符串表示一个文档的结尾,下一个文档的开始。

以下配置代表两个逻辑文件

spring:application:name: "MyApp"
---
spring:application:name: "MyCloudApp"config:activate:on-cloud-platform: "kubernetes"

对于properties属性文件 使用 #— 、!— 字符串分隔文件

spring.application.name=MyApp
#---
spring.application.name=MyCloudApp
spring.config.activate.on-cloud-platform=kubernetes

Activation Properties

在一些场景中,当条件满足时,需要激活相关的属性配置。可以使用 spring.config.activate.*. 有条件的技术配置属性。

PropertyNote
on-profile表达式与配置文件匹配,才能激活相关属性
on-cloud-platform当配置处于活动状态,CloudPlatform配置值才被有效
myprop:"always-set"
---
spring:config:activate:on-cloud-platform: "kubernetes"on-profile: "prod | staging"
myotherprop: "sometimes-set"

Working With YAML

YAML是一个分层的、格式良好的数据配置文件,跟JSON数据一样,也是Key-Value数据格式存储。Spring Boot 内部使用SnakeYAML 第三方 jar包 支持 YAML格式文件的解析。

如果使用Starter包,SnakeYAML jar包已经被包含在 spring-boot-starter.

Mapping YAML to Properties

YAML 文档根据其分层结构转换为 Key-Value键值对存储在Spring Environment 环境中,例如:

environments:dev:url: "https://dev.example.com"name: "Developer Setup"prod:url: "https://another.example.com"name: "My Cool App"

Spring Environment 内部存储的数据结构如下:

environments.dev.url=https://dev.example.com
environments.dev.name=Developer Setup
environments.prod.url=https://another.example.com
environments.prod.name=My Cool App

同时,YAML支持组数配置,使用 [index] 解析器表示数组下标,如:

my:servers:- "dev.example.com"- "another.example.com"

上述example将被转换为:

my.servers[0]=dev.example.com
my.servers[1]=another.example.com

Directly Loading YAML

Spring Framework 提供了两个类来加载YAML配置文件

  • YamlPropertiesFactoryBean - 将YAML作为properties属性加载
  • YamlMapFactoryBean - 将YAML作为Map加载

配置随机属性

RandomValuePropertySource 类用于注入随机配置属性(例如,配置秘钥、测试用例)。可以生成Integer、Long、uuids、strings,配置如下:

my:secret: "${random.value}"number: "${random.int}"bignumber: "${random.long}"uuid: "${random.uuid}"number-less-than-ten: "${random.int(10)}"number-in-range: "${random.int[1024,65536]}"

Type-safe Configuration Properties

使用@Value(“${property}”)注解注入属性文件时,有些时候可能存在问题。尤其是使用多个属性、或者数据分层时,Spring Boot 提供了另一种处理属性的方法,它允许强类型bean管理、验证应用程序的配置。

JavaBean 属性绑定

绑定Bean中定义的属性值(Get、Set方法),使用如下:

@ConfigurationProperties("my.service")
public class MyProperties {private boolean enabled;private InetAddress remoteAddress;private final Security security = new Security();// getters / setters...public static class Security {private String username;private String password;private List roles = new ArrayList<>(Collections.singleton("USER"));// getters / setters...}
}

Bean 与 配置文件之间的对应关系为:

  • my.service.enabled 对应 enabled属性,默认值为 false
  • my.service.remote-address 对应remoteAddress属性,配置为字符串
  • my.service.security.username 对应内部类Security中的name属性
  • my.service.security.password 对应内部类Security中的password属性
  • my.service.security.roles 对应内部类roles属性,配置为String 数组

构造函数绑定

Spring Boot 支持以构造函数方式注入配置属性值,代码如下:

import java.net.InetAddress;
import java.util.List;import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConstructorBinding;
import org.springframework.boot.context.properties.bind.DefaultValue;@ConstructorBinding
@ConfigurationProperties("my.service")
public class MyProperties {private final boolean enabled;private final InetAddress remoteAddress;private final Security security;public MyProperties(boolean enabled, InetAddress remoteAddress, Security security) {this.enabled = enabled;this.remoteAddress = remoteAddress;this.security = security;}public boolean isEnabled() {return this.enabled;}public InetAddress getRemoteAddress() {return this.remoteAddress;}public Security getSecurity() {return this.security;}public static class Security {private final String username;private final String password;private final List roles;public Security(String username, String password, @DefaultValue("USER") List roles) {this.username = username;this.password = password;this.roles = roles;}public String getUsername() {return this.username;}public String getPassword() {return this.password;}public List getRoles() {return this.roles;}}
}

@ConstructorBinding注解用于指定使用构造函数绑定配置属性值,内部类的构造函数也可以使用该注解绑定属性值。

通过构造函数绑定属性值时,可以使用@DefaultValue注解设置属性默认值。

引用之前的带啊,如果文件中没有配置 Security值,MyProperties 实例中 security字段设置为null。为了避免null值,可以通过 @DefaultValue 指定默认值,如下:

public MyProperties(boolean enabled, InetAddress remoteAddress, @DefaultValue Security security) {this.enabled = enabled;this.remoteAddress = remoteAddress;this.security = security;
}

使用构造函数绑定,Spring Boot应用程序必须开启 @EnableConfigurationProperties 属性、或者配置属性扫描。不能使用构造函数绑定来创建 @Component 声明的bean

Enabling @ConfigurationProperties-annotated Types

Spring Boot 提供 @ConfigurationProperties 声明一个class文件,并将它注册为bean。可以单个启动配置属性,也可以通过扫描启动多个配置属性。

使用@ConfigurationProperties注释的类可能不适合扫描,例如开发自定义的配置,并希望有条件的启用他们。此类情况请使用@EnableConfigurationProperties注解要处理的class类型。需要跟 @configuration配合使用。

import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(SomeProperties.class)
public class MyConfiguration {}

进行配置文件扫描时,需要在应用程序增加 @ConfigurationPropertiesScan 注解,一般加在启动类上。默认情况下,从注解中声明的package进行扫描,如果需要指定特殊的package,代码如下:

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;@SpringBootApplication
@ConfigurationPropertiesScan({ "com.example.app", "com.example.another" })
public class MyApplication {}

Relaxed Binding

Spring Boot 使用宽松的规则来匹配配置文件中对的key值,跟class内定义的字段值。

import org.springframework.boot.context.properties.ConfigurationProperties;@ConfigurationProperties(prefix = "my.main-project.person")
public class MyPersonProperties {private String firstName;public String getFirstName() {return this.firstName;}public void setFirstName(String firstName) {this.firstName = firstName;}}
PropertyNote
my.main-project.person.first-nameproperties、yml文件推荐使用方式,最后的字段值自动转换为驼峰式命名
my.main-project.person.firstName标准的驼峰式命名
my.main-project.person.first_name.properties、yml 文件可选的数据格式之一
MY_MAINPROJECT_PERSON_FIRSTNAME大写形式,在定义系统环境变量中推荐使用

相关内容

热门资讯

阿里千问App全球首发点外卖、... 1月15日,阿里举行千问App发布会, 阿里巴巴(BABA.US)集团副总裁吴嘉宣布,千问App全面...
携程港股、美股放量跌近20% 【大河财立方消息】1月15日,携程港股、美股双双大跌。 截至发稿,港股携程集团跌幅18.53%,美股...
淳厚基金获国资入主!管理规模缩... 淳厚基金获得长宁国投入主,但是市场声誉遭遇重挫,机构投资者纷纷撤出。 文/每日财报 楚风 随着国有...
「死了么」爆火,1亿独居群体被... 「核心提示」 独居时代下的深层焦虑,让“死了么”迎来短暂流量狂欢。不过,这款低门槛应用,拿什么...
2025年我国跨境电商进出口2... 一、明星品牌 1、美国奢侈品零售商萨克斯环球申请破产保护 美国高端百货集团萨克斯环球(Saks Gl...
卫龙前CEO孙亦农入职大窑出任... 红星资本局1月15日消息,红星资本局从大窑处了解到,卫龙(09985.HK)前CEO孙亦农已加入大窑...
市场利好持续提振港股医药股 东... 财联社1月15日讯(编辑 胡家荣)今日港股医药板块迎来强劲反弹,多只个股表现亮眼。截至发稿,东曜药业...
技术派登顶!2026浙江危机公... 2026年危机公关行业正经历近十年来最深刻的范式革命。当抖音热搜的存活周期缩短至3小时、AI生成虚假...
雷军官宣今晚直播:与汽车媒体一... 2026年1月15日,小米创办人,董事长兼CEO雷军在社交媒体平台发文称,“上次直播后,很多网友希望...
阿里千问宣布接入淘宝、支付宝、... 1月15日,阿里千问App宣布全面接入淘宝、支付宝、淘宝闪购、飞猪、高德等阿里生态业务,在全球首先实...
黄金投资交易入门:定义与风险评... 黄金投资交易是以黄金为交易标的的金融投资行为,核心是通过把握黄金价格的波动规律,以低买高卖的方式赚取...
第六批高值医用耗材集采开标,涉... 图片来源:视觉中国 蓝鲸新闻1月14日讯(记者 屠俊)据国家医保局官微信息显示,1月13日,第六批国...
瑞银:中国AI不堆卡、重效率,... “中国AI行业不存在美国式泡沫,反而将在模型出海、应用爆发、算力替代三大主线迎来系统性机遇。”1月1...
小鹏汇天冲击港股IPO:低空经... 2026年刚刚开始,小鹏汇天秘密提交港股IPO申请的消息就不胫而走。 有知情人士透露,小鹏汽车已聘请...
原创 马... 这将是一段动荡的旅程。 一 几周前,美国德州特斯拉超级工厂内,马斯克接受一次特殊访谈,预言2026。...
梁文锋旗下幻方量化,去年收益率... 每经记者|杨建 每经编辑|何小桃 叶峰 2025年A股市场持续火热,百亿私募交出了怎样的成绩单?据...
宽基ETF规模大增的三大理由 2026年,A股市场开局向好。Wind资讯数据显示,截至1月14日,开年以来ETF总规模增长超220...
冬季护眼 “睛”彩相伴|武汉普... 冬季天气寒冷干燥,室内取暖设备的使用让空气湿度降低,加上户外活动减少、长时间近距离用眼成为常态,干眼...
白银首破92美元,金铜锡拉升创... 2026年开年以来,全球金属市场迎来新一轮狂欢。 1月14日亚太交易时段,现货白银(伦敦银现)史上首...