Spring Boot 可以通过 properties 文件, YAML 文件, 环境变量和命令行参数进行配置. 属性值可以通过,@Value 注解, Environment 或者 ConfigurationProperties 注入到应用中. 配置的优先级如下:
如果使用了 devtools, 则以 home 目录下的
~/.spring-boot-devtools.properties
为主
@TestPropertySource
注解的测试
@SpringBootTest#properties
注解的测试
命令行参数
SPRING_APPLICATION_JSON
提供的属性(JSON 格式, 从环境变量或者系统属性中获取)
ServletConfig 配置的属性
ServletContext 配置的属性
JNDI 配置的属性,(java:comp/env)
Java 系统属性,
System.getProperties()
系统环境变量
RandomValuePropertySource
进针对于 random.*
jar 包外部指定 profile 文件, 例如 application-{profile}.properties(YAML 同)
jar 包内部的指定 profile 文件
应用外部的 application.properties
应用内部的 application.properties
@PropertySource 注解
默认属性(
SpringApplication.setDefaultProperties()
) 例如:
- import org.springframework.stereotype.*
- import org.springframework.beans.factory.annotation.*
- @Component
- public class MyBean {
- @Value("${name}")
- private String name;
- // ...
- }
在
application.properties
提供了 name 的默认值, 当运行程序的时候可以通过提供命令行的值覆盖其默认值,
- java -jar app.jar --name="spring"
- .
配置随机值
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 会将命令行参数转换为 property 并添加到 Environment 中. 正如前面提到的, 命令行参数会覆盖其他的配置. 如果不希望命令行参数添加到 Environment 中可以通过调用
SpringApplication.setAddCommandLineProperties(fals)
设置.
应用配置文件
SpringApplication 加载
application.properties
文件, 将其变量添加到 Environment 中, 查找位置: 1. 当前目录的 / config 目录 2. 当前目录 3. classpath 下的 config 子目录 4. classpath 目录 如果不想使用
application.properties
文件可以使用 spring.config.name 指定配置名字, 同样可以通过
spring.config.location
指定配置文件的位置
- java -jar myproject.jar --spring.config.name=myproject
- java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties
如果
spring.config.location
使用的是目录, 那么其应该以 / 结尾, 运行的时候会将
spring.confing.name
的名字追加到后来查找配置文件.
指定配置文件
除了
application.properties
文件外, 同样可以以
application-{profile}.properties
的形式命名指定配置文件. Environment 有一个默认的配置,(default), 即如果没有激活其他配置文件, 默认使用
application-default.properties
. 如果提供了多个指定配置文件, 则选择最新的配置文件.
配置文件的占位符
application.properties
中的定义的值可以在后续的配置中使用, 例如
- app.name=MyApp
- app.description=${app.name} is a Spring Boot application
使用 YAML 配置文件
当添加了 SnakeYAML 时, SpringApplication 即可支持 YAML 配置, 添加 spring-boot-starter 自动会添加对 SnakeYAML 的依赖.
加载 YAML
SpringApplication 有两种加载 YAML 配置文件的方式, 1. 使用
YamlPropertiesFactoryBean
将 YAML 加载为 Properties,2. 使用 YamlMapFactoryBean 将 YAML 加载为 map. 以下 YAML 配置文件:
- environments:
- dev:
- url: http://dev.example.com
- name: Developer Setup
- prod:
- url: http://another.example.com
- name: My Cool App
上面的配置文件等同的 properties 配置
- 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 列表默认会添加序号 (index) 例如:
- my:
- servers:
- - dev.example.com
- - another.example.com
等同的 properties 配置为
- my.servers[0]=dev.example.com
- my.servers[1]=another.example.com
可以通过
@ConfigurationProperties
注解将属性绑定到变量中, 例如:
- @ConfigurationProperties(prefix="my")
- public class Config {
- private List<String> servers = new ArrayList<String>();
- public List<String> getServers() {
- return this.servers;
- }
- }
多个 YAML 配置文件
可以在单个文件中使用 spring.profiles 作为 key 指定多个 YAML 配置文件. 例如:
- server:
- address: 192.168.1.100
- ---
- spring:
- profiles: development
- server:
- address: 127.0.0.1
- ---
- spring:
- profiles: production
- server:
- address: 192.168.1.120
按照上述文件表示, 如果 development 配置激活了, 则 server.address 设置为 127.0.0.1. 同样的, 如果 production 配置激活则 server.address 配置为 192.168.1.120. 如果 development 和 production 都没有启用, 则使用默认即 server.address 设置为 192.168.1.100 如果没有指定激活哪个配置, 那么默认使用 default 的配置, 例如以下示例,
spring.security.user.password
只有在都不指定激活配置的时候才会使用
- server:
- port: 8000
- ---
- spring:
- profiles: default
- security:
- user:
- password: weak
下面的例子密码都会被设置, 因为他不属于任何一个配置:
- server:
- port: 8000
- spring:
- security:
- user:
- password: weak
使用 @ConfigurationProperties 注入值
从多个 properties 注入值的时候使用 @Value()非常的麻烦, Spring Boot 可以使用 @ConfigurationProperties 进行简化配置, 例如:
- 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("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.enable=false
- acme.remote-address=192.168.1.1
- acme.security.username=username
- acme.security.password=password
- acme.security.roles=roles1,roles2
需要在 @Configuration 的配置中起用
- @Configuration
- @EnableConfigurationProperties(AcmeProperties.class)
- public class MyConfiguration {
- }
当然如果 AcmeProperties 类是一个 bean 则无需配置指定
@EnableConfigurationProperties(AcmeProperties.class)
例如:
- @Component
- @ConfigurationProperties(prefix="acme")
- public class AcmeProperties {
- // ... see the preceding example
- }
等同的 YAML 配置文件
- acme:
- remote-address: 192.168.1.1
- security:
- username: admin
- roles:
- - USER
- - ADMIN
松绑定规则
通过 @ConfigurationProperties 绑定变量非常的灵活, 例如:
- @ConfigurationProperties(prefix="acme.my-project.person")
- public class OwnerProperties {
- private String firstName;
- public String getFirstName() {
- return this.firstName;
- }
- public void setFirstName(String firstName) {
- this.firstName = firstName;
- }
- }
对于下列的方式都可以成功绑定
- acme.my-porject.person.first-name
- acme.my-project.person.first_name
- acme.my-project.person.firstName
- ACME_MYPROJECT_PERSON_FIRSTNAME
@ConfigurationProperties 校验
@ConfigurationProperties 支持 JSR-303 javax.validation 注解进行校验, 例如
- @ConfigurationProperties(prefix="acme")
- @Validated
- public class AcmeProperties {
- @NotNull
- private InetAddress remoteAddress;
- // ... getters and setters
- }
@ConfigurationProperties 和 @Value 的区别
功能 | @configurationProperties | @Value |
---|---|---|
松绑定规则 | Y | N |
元数据支持 | Y | N |
SPEL | N | Y |
Profiles
Spring Profile 可以将应用的配置分成多部分, 只有在指定的环境下生效. 任何 @component 或者 @Configutaion 都可以使用 @Profile 限制其加载, 例如
- @Configuration
- @Profile("production")
- public class ProductionConfiguration {
- // ...
- }
可以使用
spring.profiles.active
的 Environment 变量设置激活哪个 profile. 例如在 application.properties 中设置
spring.profiles.active=dev,hsqldb
或者使用命令行
java -jar app.jar --spring.profiles.active=dev,hsqldb
来源: https://juejin.im/entry/5b00e9ac6fb9a07aac24bacc