文章目录
基于SpringBoot
v2.2.4.RELEASE
官方文档
外部配置
Spring Boot中可以使用外部配置,以便在不同的环境中使用相同的代码。你可以使用 properties
文件、YAML
文件、环境变量
和命令行参数
来配置。
1、配置随机值
RandomValuePropertySource
在注入随机值时是十分有用的。例如进入隐私的或者测试的例子。它可以产生整数、longs、uuid或字符串,如下所示:
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]}
random.int*
语法可以带有参数。
- random.int
- random.int(value)
- random.int(value, max) ——如果有
max
,value
提供的就是最小值。value
和max
都是整数。
2、命令行配置属性
所有的属性配置都可以在命令行上进行指定。例如:
java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --server.port=8087 --server.context-path=/abc
默认情况下,SpringApplication
将所有命令行选项参数转换为a property
并将其添加到Spring Environment
。
如果不希望将命令行属性添加到Environment
,可以使用SpringApplication.setAddCommandLineProperties(false)
来禁用。
3、Application Property 文件
SpringApplication
从以下位置的application.properties
文件中加载属性,并将其添加到Spring Environment
:
- 当前目录的一个
/config
子目录下(file:./config/
); - 当前目录(
file:./
); - 类路径的
/config
包(classpath:/config/
); - 类路径下(
classpath:/
)
优先级由高到底,高优先级的配置会覆盖低优先级的配置;
可以使用YAML(.yml)来代替
.properties
如果不喜欢application.properties
作为配置文件的名称,可以通过指定 spring.config.name
来使用另一个文件名。另外,还可以配置 spring.config.location
来改变默认的配置文件位置。
#指定其他文件名
$ java -jar myproject.jar --spring.config.name = myproject
项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置。
如果要指定配置文件和默认加载的这些配置文件共同起作用形成互补配置,需要使用spring.config.additional-lacation
;
#指定配置文件加载位置,如果有多个,用逗号隔开
$ java -jar spring-boot-02-config-02-0.0.1-SNAPSHOT.jar --spring.config.location=G:/application.properties
配置文件是以相反的顺序搜索。默认情况下,configured locations
是 classpath:/,classpath:/config/,file:./,file:./config/
。但搜索顺序的结果正好相反。
当通过 spring.config.lacation
自定义配置位置后,它们就会取代默认位置。并且如果spring.config.location
配置为classpath:/custom-config/,file:./custom-config/
,则搜索顺序将变为:
file:./custom-config/
classpath:custom-config/
当使用spring.config.additional-location
配置时,除了默认位置外,还会使用配置的值。
- 可以在一个配置文件中指定默认值,然后在另一配置文件中选择性的覆盖这些值。
- 如果你使用 environment变量而不是 system 属性,大多数操作系统都不允许使用
.
分割的键名,这是可以使用_
代替。(SPRING_CONFIG_NAME
代替spring.config.name
)。
4、profile
Profile可以为不同环境提供不同配置,可以通过激活、指定参数等方式快速切换环境。
在编写配置文件时,文件名可以是 application-{profile}.properties
。默认使用application-default.properties
(即application.properties
)加载属性。
application-{profile}.properties
文件能够从application.properties
的位置加载。
不论application-{profile}.properties
文件是在jar包外还是内部,他都可以覆盖application.properties
用法:
指定两种环境,分别为dev 和 prod:
#application-dev.properties
server.port=8081
#application-prod.properties
server.port=8082
激活profile有三种方法:
-
配置文件中指定
#application.properties spring.profiles.active=dev #启动后端口号为8081
-
命令行指定
java -jar spring-boot-02-config-0.0.1-SNAPSHOT.jar --spring.profiles.active=dev;
也可以在idea启动前,配置传入参数:
-
虚拟机指定
如上图
5、加密属性值
Spring Boot不提供任何内置的对属性值加密的支持。
6、YAML的使用
Spring Framework提供了两个方便的类来加载YAML文件。
YamlPropertiesFactoryBean
将YAML 加载为Properties
YamlMapFactoryBean
将YAML 加载为Map
6.1 YAML语法
environments:
dev:
url: https://dev.example.com
name: Developer Setup
prod:
url: https://another.example.com
name: My Cool App
以上的YAML文档将会转化为以下properties:
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
List表示:
my:
servers:
- dev.example.com
- another.example.com
以上的YAML文档将会转化为以下properties:
my.servers[0]=dev.example.com
my.servers[1]=another.example.com
6.2 多文档块方式
server:
port: 8081
#spring:
# profiles:
# active: dev
---
server:
port: 8082
spring:
profiles: dev
---
server:
port: 8083
spring:
profiles: prod
在上面的例子中,如果dev
配置文件处于活动状态,则server.port
属性为8082
。如果prod
配置文件处于活动状态,则server.port
属性为8083
。上面的文档中spring.profiles.active
注释了,因此server.port
属性为8081
。
6.3 YAML的缺点
不能通过@PropertySource
来加载YAML配置文件,所以如果想要通过这种方式加载值,只能使用properties
文件。
#person.properties
person.name: zhangsan
person.age: 10
person.address: 陕西省
person.birthday: 2017/10/20
@Component
@PropertySource(value = {"classpath:person.properties"})
@ConfigurationProperties(prefix = "person")
public class Person {
private String name;
private int age;
private String address;
private Date birthday;
//...省略getter和setter方法
}
在profile中使用YAML的多文档块方式可以会出现问题。
官方建议不要混合使用 YAML格式的profile文档
和YAML的多文档块
,坚持只使用其中一个。
7、配置属性的类型安全
7.1 配置文件注入JavaBean
#application.yml
person:
lastName: hello
age: 18
boss: false
birth: 2017/12/12
maps: {k1: v1,k2: 12}
lists:
- lisi
- zhaoliu
dog:
name: 小狗
age: 12
/**
* 将配置文件中配置的每一个属性的值,映射到这个组件中
* @ConfigurationProperties:告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定;
* prefix = "person":配置文件中person下面的所有属性进行一一映射
*
* 使用@Component将该类称为容器中的组件
* 只有这个组件是容器中的组件,才能使用容器提供的@ConfigurationProperties功能;
*
*/
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String lastName;
private Integer age;
private Boolean boss;
private Date birth;
private Map<String,Object> maps;
private List<Object> lists;
private Dog dog;
//...省略getter和setter方法
}
可以通过
properties文件
、YAML文件
、外部环境变量
等配置。通常情况下,
getters/setters
是强制要求的,因为值的绑定是通过标准的 Java Beans 属性描述符实现的。在下列情况中,setter
才可以忽略:
7.2 构造函数绑定
测试出现问题
7.3 @ConfigurationProperties
7.4 松散绑定
SpringBoot使用松散的规则将 properties
绑定到 @ConfigurationProperties
注解的beans上。
常见的例子包括
user-name
绑定到userName
PORT
绑定到port
现有以下 @ConfigurationProperties
注解的类
@Component
@ConfigurationProperties(prefix="person")
public class person {
private String firstName;
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
使用上面的的代码,下面的这些 properties
名称都能够使用:
Properties | 描述 |
---|---|
person.first-name | 短横线命名,建议在.properties 和.yml 文件中使用 |
person.firstName | 标准驼峰式命名 |
person.first_name | 下划线表示法,是在.properties 和.yml 文件中使用的另一种格式。 |
PERSON_FORSTNAME | 大写的格式,通常使用于系统环境变量 |
prefix
的值必须使用短横线命名法
(小写字母,以-
分隔开,例如acme.my-project.person
)
不同属性的松散绑定规则
Property Source | 简单 | List |
---|---|---|
Properties文件 | 短横线命名,驼峰式命名 或 下划线表示法 | 使用[ ]或逗号分隔的标准列表语法 |
YAML文件 | 短横线命名,驼峰式命名 或 下划线表示法 | YAML列表语法或者逗号分隔的值 |
环境变量 | 以_ 作为定界符的大写格式,_ 不应在属性名称中使用 | 下划线括起来的数值,例如 MY_ACME_1_OTHER = my.acme[1].other |
系统属性 | 短横线命名,驼峰式命名 或 下划线表示法 | 使用[ ]或逗号分隔的标准列表语法 |
7.5 @ConfigurationProperties数据校验
如果 @ConfigurationProperties
标注的类被 @Validated
注解,SpringBoot就会对该类的数据进行校验。
你能够直接使用 JSR-303
数据校验。
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
@Email //必须是邮箱
private String email;
@NotNull //不能为null
private InetAddress remoteAddress;
}
为了确保嵌套属性的验证,相关的字段必须使用 @Valid
注解,示例:
/*Dog.java*/
public class Dog {
private Long id;
@Email
private String name;
private String type;
//...省略getter和setter方法
}
/*Person.java*/
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
@NotNull
private String name;
private int age;
private String address;
private Date birthday;
@Valid
private Dog dog = new Dog();
//...省略getter和setter方法
}
你可以通过创建一个名为configurationPropertiesValidator
的bean自定义Spring 的Validator
,该@Bean
的方法应该声明为static
。
7.6 @ConfigurationProperties与@Value
@ConfigurationProperties | @Value | |
---|---|---|
功能 | 批量注入配置文件中的属性 | 一个个指定 |
松散绑定 | 支持 | 不支持 |
SpEL | 不支持 | 支持 |
JSR303数据校验 | 支持 | 不支持 |
复杂类型封装 | 支持 | 不支持 |
如果我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value
;
如果我们专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties
;
最后,虽然你能够在@Value
写一个SPEL
表达式,但从application property
文件中获取的属性表达式不能处理。
@Value("${person.Name}") //可以获取到properties中的值
private String name;
@Value("${person.age * 2}") //可以获取到值,但不能处理,该处报错!!!
private int age;