SpringBoot 之属性读写详解
* 加载 property 顺序
<https://www.cnblogs.com/jingmoxukong/p/10153716.html#加载-property-顺序>
* 随机属性 <https://www.cnblogs.com/jingmoxukong/p/10153716.html#随机属性>
* 命令行属性 <https://www.cnblogs.com/jingmoxukong/p/10153716.html#命令行属性>
* Application 属性文件
<https://www.cnblogs.com/jingmoxukong/p/10153716.html#application-属性文件>
* Profile 特定属性
<https://www.cnblogs.com/jingmoxukong/p/10153716.html#profile-特定属性>
* 属性中的占位符 <https://www.cnblogs.com/jingmoxukong/p/10153716.html#属性中的占位符>
* YAML 属性 <https://www.cnblogs.com/jingmoxukong/p/10153716.html#yaml-属性>
* 访问属性 <https://www.cnblogs.com/jingmoxukong/p/10153716.html#访问属性>
* 多 profile 配置
<https://www.cnblogs.com/jingmoxukong/p/10153716.html#多-profile-配置>
* YAML 的缺点 <https://www.cnblogs.com/jingmoxukong/p/10153716.html#yaml-的缺点>
* 属性前缀 <https://www.cnblogs.com/jingmoxukong/p/10153716.html#属性前缀>
* 属性松散绑定规则 <https://www.cnblogs.com/jingmoxukong/p/10153716.html#属性松散绑定规则>
* 属性转换 <https://www.cnblogs.com/jingmoxukong/p/10153716.html#属性转换>
* 时间单位转换 <https://www.cnblogs.com/jingmoxukong/p/10153716.html#时间单位转换>
* 数据大小转换 <https://www.cnblogs.com/jingmoxukong/p/10153716.html#数据大小转换>
* 校验属性 <https://www.cnblogs.com/jingmoxukong/p/10153716.html#校验属性>
* 源码 <https://www.cnblogs.com/jingmoxukong/p/10153716.html#源码>
* 引申和引用 <https://www.cnblogs.com/jingmoxukong/p/10153716.html#引申和引用>
加载 property 顺序
Spring Boot 加载 property 顺序如下:
* Devtools 全局配置
<https://docs.spring.io/spring-boot/docs/2.1.1.RELEASE/reference/htmlsingle/#using-boot-devtools-globalsettings>
(当 devtools 被激活~/.spring-boot-devtools.properties).
* 测试环境中的 @TestPropertySource 注解配置
<https://docs.spring.io/spring/docs/5.1.3.RELEASE/javadoc-api/org/springframework/test/context/TestPropertySource.html>
* 测试环境中的属性 properties:@SpringBootTest
<https://docs.spring.io/spring-boot/docs/2.1.1.RELEASE/api/org/springframework/boot/test/context/SpringBootTest.html>
和测试注解
<https://docs.spring.io/spring-boot/docs/2.1.1.RELEASE/reference/htmlsingle/#boot-features-testing-spring-boot-applications-testing-autoconfigured-tests>
.
* 命令行参数
* SPRING_APPLICATION_JSON 属性
* ServletConfig 初始化参数
* ServletContext 初始化参数
* JNDI attributes from 通过 java:comp/env 配置的 JNDI 属性
* Java 系统属性 (System.getProperties())
* 操作系统环境比那里
* RandomValuePropertySource 加载 random.* 形式的属性
* jar 包外的 application-{profile}.properties 或 application-{profile}.yml 配置
* jar 包内的 application-{profile}.properties 或 application-{profile}.yml 配置
* jar 包外的 application.properties 或 application.yml 配置
* jar 包内的 application.properties 或 application.yml 配置
* @PropertySource 绑定的配置
* 默认属性 (通过 SpringApplication.setDefaultProperties 指定)
随机属性
RandomValuePropertySource 类用于配置随机值。
示例:
my.secret=${random.value} my.number=${random.int} my.bignumber=${random.long}
my.uuid=${random.uuid} my.number.less.than.ten=${random.int(10)}
my.number.in.range=${random.int[1024,65536]}
命令行属性
默认情况下, SpringApplication 会获取 -- 参数(例如 --server.port=9000 ),并将这个 property 添加到
Spring 的Environment 中。
如果不想加载命令行属性,可以通过 SpringApplication.setAddCommandLineProperties(false) 禁用。
Application 属性文件
SpringApplication 会自动加载以下路径下的 application.properties 配置文件,将其中的属性读到 Spring 的
Environment 中。
* 当前目录的 /config 子目录
* 当前目录
* classpath 路径下的 /config package
* classpath 根路径
注:
以上列表的配置文件会根据顺序,后序的配置会覆盖前序的配置。
你可以选择 YAML(yml)
<https://docs.spring.io/spring-boot/docs/2.1.1.RELEASE/reference/htmlsingle/#boot-features-external-config-yaml>
配置文件替换 properties 配置文件。
如果不喜欢 application.properties 作为配置文件名,可以使用 spring.config.name 环境变量替换:
$ java -jar myproject.jar --spring.config.name=myproject
可以使用 spring.config.location 环境变量指定配置文件路径:
$ java -jar myproject.jar
--spring.config.location=classpath:/default.properties,classpath:/override.properties
Profile 特定属性
如果定义 application-{profile}.properties 形式的配置文件,将被视为 profile 环境下的特定配置。
可以通过 spring.profiles.active 参数来激活 profile,如果没有激活的 profile,默认会加载
application-default.properties 中的配置。
属性中的占位符
application.properties 中的值会被 Environment 过滤,所以,可以引用之前定义的属性。
app.name=MyApp app.description=${app.name} is a Spring Boot application
注:你可以使用此技术来创建 Spring Boot 属性变量。请参考: Section 77.4, “Use ‘Short’ Command Line
Arguments
<https://docs.spring.io/spring-boot/docs/2.1.1.RELEASE/reference/htmlsingle/#howto-use-short-command-line-arguments>
YAML 属性
Spring Framework provides two convenient classes that can be used to load YAML
documents. TheYamlPropertiesFactoryBean loads YAML as Properties and the
YamlMapFactoryBean loads YAML as a Map.
Spring 框架有两个类支持加载 YAML 文件。
* YamlPropertiesFactoryBean 将 YAML 文件的配置加载为 Properties 。
* YamlMapFactoryBean 将 YAML 文件的配置加载为 Map 。
示例 1
environments: dev: url: http://dev.example.com name: Developer Setup prod:
url: http://another.example.com name: My Cool App
等价于:
environments.dev.url=http://dev.example.com environments.dev.name=Developer
Setup environments.prod.url=http://another.example.com
environments.prod.name=My Cool App
YAML 支持列表形式,等价于 property 中的 [index] :
my: servers: - dev.example.com - another.example.com
等价于
my.servers[0]=dev.example.com my.servers[1]=another.example.com
访问属性
YamlPropertySourceLoader 类会将 YAML 配置转化为 Spring Environment 类中的 PropertySource
。然后,你可以如同 properties 文件中的属性一样,使用@Value 注解来访问 YAML 中配置的属性。
多 profile 配置
server: address: 192.168.1.100 --- spring: profiles: development server:
address: 127.0.0.1 --- spring: profiles: production & eu-central server:
address: 192.168.1.120
YAML 的缺点
注:YAML 注解中的属性不能通过 @PropertySource 注解来访问。所以,如果你的项目中使用了一些自定义属性文件,建议不要用 YAML。
属性前缀
package com.example; import java.net.InetAddress; import java.util.ArrayList;
import java.util.Collections; import java.util.List; import
org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix="acme") public class AcmeProperties { private
boolean enabled; private InetAddress remoteAddress; private final Security
security = new Security(); public boolean isEnabled() { ... } public void
setEnabled(boolean enabled) { ... } public InetAddress getRemoteAddress() { ...
} public void setRemoteAddress(InetAddress remoteAddress) { ... } public
Security getSecurity() { ... } public static class Security { private String
username; private String password; private List<String> roles = new
ArrayList<>(Collections.singleton("USER")); public String getUsername() { ... }
public void setUsername(String username) { ... } public String getPassword() {
... } public void setPassword(String password) { ... } public List<String>
getRoles() { ... } public void setRoles(List<String> roles) { ... } } }
相当于支持配置以下属性:
* acme.enabled
* acme.remote-address
* acme.security.username
* acme.security.password
* acme.security.roles
然后,你需要使用 @EnableConfigurationProperties 注解将属性类注入配置类中。
@Configuration @EnableConfigurationProperties(AcmeProperties.class) public
class MyConfiguration { }
属性松散绑定规则
Spring Boot 属性名绑定比较松散。
以下属性 key 都是等价的:
Property Note
acme.my-project.person.first-name - 分隔
acme.myProject.person.firstName 驼峰命名
acme.my_project.person.first_name _ 分隔
ACME_MYPROJECT_PERSON_FIRSTNAME 大写字母
属性转换
如果需要类型转换,你可以提供一个 ConversionService bean (一个名叫 conversionService 的 bean)
或自定义属性配置 (一个CustomEditorConfigurer bean) 或自定义的 Converters (被
@ConfigurationPropertiesBinding 注解修饰的 bena)。
时间单位转换
Spring 使用 java.time.Duration 类代表时间大小,以下场景适用:
* 除非指定 @DurationUnit ,否则一个 long 代表的时间为毫秒。
* ISO-8601 标准格式( java.time.Duration
<https://docs.oracle.com/javase/8/docs/api//java/time/Duration.html#parse-java.lang.CharSequence->
的实现就是参照此标准)
* 你也可以使用以下支持的单位:
* ns - 纳秒
* us - 微秒
* ms - 毫秒
* s - 秒
* m - 分
* h - 时
* d - 天
示例:
@ConfigurationProperties("app.system") public class AppSystemProperties {
@DurationUnit(ChronoUnit.SECONDS) private Duration sessionTimeout =
Duration.ofSeconds(30); private Duration readTimeout = Duration.ofMillis(1000);
public Duration getSessionTimeout() { return this.sessionTimeout; } public void
setSessionTimeout(Duration sessionTimeout) { this.sessionTimeout =
sessionTimeout; } public Duration getReadTimeout() { return this.readTimeout; }
public void setReadTimeout(Duration readTimeout) { this.readTimeout =
readTimeout; } }
数据大小转换
Spring 使用 DataSize 类代表数据大小,以下场景适用:
* long 值(默认视为 byte)
* 你也可以使用以下支持的单位:
* B
* KB
* MB
* GB
* TB
示例:
@ConfigurationProperties("app.io") public class AppIoProperties {
@DataSizeUnit(DataUnit.MEGABYTES) private DataSize bufferSize =
DataSize.ofMegabytes(2); private DataSize sizeThreshold =
DataSize.ofBytes(512); public DataSize getBufferSize() { return
this.bufferSize; } public void setBufferSize(DataSize bufferSize) {
this.bufferSize = bufferSize; } public DataSize getSizeThreshold() { return
this.sizeThreshold; } public void setSizeThreshold(DataSize sizeThreshold) {
this.sizeThreshold = sizeThreshold; } }
校验属性
@ConfigurationProperties(prefix="acme") @Validated public class AcmeProperties
{ @NotNull private InetAddress remoteAddress; @Valid private final Security
security = new Security(); // ... getters and setters public static class
Security { @NotEmpty public String username; // ... getters and setters } }
你也可以自定义一个名为 configurationPropertiesValidator 的校验器 Bean。获取这个 @Bean 的方法必须声明为
static。
源码
完整示例:源码
<https://github.com/dunwu/spring-boot-tutorial/tree/master/codes/core/sbe-core-property>
使用方法:
mvn clean package cd target java -jar sbe-core-property.jar
引申和引用
引申
* Spring Boot 教程 <https://github.com/dunwu/spring-boot-tutorial>
参考
* Spring Boot 官方文档之 boot-features-external-config
<https://docs.spring.io/spring-boot/docs/2.1.1.RELEASE/reference/htmlsingle/#boot-features-external-config>
热门工具 换一换