配置文件
Spring Boot 配置文件
Spring Boot 针对我们常用的开发场景提供了一系列自动化配置来减少原本复杂而又几乎很少改动的模板化配置内容;本部分会对 Spring Boot 中配置文件的基础使用进行介绍。Spring Boot 提供了两种常用的配置文件,分别是 properties 文件和 yml 文件;他们的作用都是修改 Spring Boot 自动配置的默认值。值得一提的是,在 Spring Boot 2.0 中推出了 Relaxed Binding 2.0,对原有的属性绑定功能做了非常多的改进以帮助我们更容易的在 Spring 应用中加载和读取配置信息。在 Spring Boot 2.0 中对配置属性加载的时候会除了像 1.x 版本时候那样移除特殊字符外,还会将配置均以全小写的方式进行匹配和加载。所以,下面的 4 种配置方式都是等价的:
spring.jpa.databaseplatform=mysql
spring.jpa.database-platform=mysql
spring.jpa.databasePlatform=mysql
spring.JPA.database_platform=mysql
spring:
jpa:
databaseplatform: mysql
database-platform: mysql
databasePlatform: mysql
database_platform: mysql
推荐使用全小写配合 -
分隔符的方式来配置,比如:spring.jpa.database-platform=mysql
。
YAML
Spring Boot 的配置文件除了可以使用传统的 properties 文件之外,还支持现在被广泛推荐使用的 YAML 文件。YAML(英语发音:/ˈjæməl/,尾音类似 camel 骆驼)是一个可读性高,用来表达资料序列的格式。YAML 参考了其他多种语言,包括:C 语言、Python、Perl,并从 XML、电子邮件的数据格式(RFC 2822)中获得灵感。YAML 采用的配置格式不像 properties 的配置那样以单纯的键值对形式来表示,而是以类似大纲的缩进形式来表示。比如:
environments:
dev:
url: http://dev.bar.com
name: Developer Setup
prod:
url: http://foo.bar.com
name: My Cool App"
# 表示数组
spring:
my-example:
url:
- http://example.com
- http://spring.io
spring:
my-example:
url: http://example.com, http://spring.io
yaml:
str: 字符串可以不加引号
specialStr: "双引号直接输出\n特殊字符"
specialStr2: '单引号可以转义\n特殊字符'
flag: false
num: 666
Dnum: 88.88
list:
- one
- two
- two
set: [1, 2, 2, 3]
map: { k1: v1, k2: v2 }
positions:
- name: wx
salary: 15000.00
- name: wxBlog
salary: 18888.88
创建实体类 YamlEntity.java 获取配置文件中的属性值,通过注解 @ConfigurationProperties 获取配置文件中的指定值并注入到实体类中。
/**
* YAML 语法实体类
* 切记点:
* 一、冒号后面加空格,即 key:(空格)value
* 二、每行参数左边空格数量决定了该参数的层级,不可乱输入。
*/
@Component
@ConfigurationProperties(prefix = "yaml")
public class YamlEntity {
// 字面值,字符串,布尔,数值
private String str; // 普通字符串
private String specialStr; // 转义特殊字符串
private String specialStr2; // 输出特殊字符串
private Boolean flag; // 布尔类型
private Integer num; // 整数
private Double dNum; // 小数
// 数组,List 和 Set,两种写法:第一种:-空格value,每个值占一行,需缩进对齐;第二种:[1,2,...n] 行内写法
private List<Object> list; // list可重复集合
private Set<Object> set; // set不可重复集合
// Map 和实体类,两种写法:第一种:key 空格 value,每个值占一行,需缩进对齐;第二种:{key: value,....} 行内写法
private Map<String, Object> map; // Map K-V
private List<Position> positions; // 复合结构,集合对象
// 省略getter,setter,toString方法
}
通过 YAML 的配置方式,我们可以看到配置信息利用阶梯化缩进的方式,其结构显得更为清晰易读,同时配置内容的字符量也得到显著的减少。除此之外,YAML 还可以在一个单个文件中通过使用 spring.profiles
属性来定义多个不同的环境配置。例如下面的内容,在指定为 test 环境时,server.port
将使用 8882 端口;而在 prod 环境,server.port
将使用 8883 端口;如果没有指定环境,server.port
将使用 8881 端口。
server:
port: 8881
---
spring:
profiles: test
server:
port: 8882
---
spring:
profiles: prod
server:
port: 8883"
YAML 目前还有一些不足,它无法通过 @PropertySource 注解来加载配置。但是,YAML 加载属性到内存中保存的时候是有序的,所以当配置文件中的信息需要具备顺序含义时,YAML 的配置方式比起 properties 配置文件更有优势。
命名约定
在 Spring Boot 2.0 中对配置属性加载的时候会除了像 1.x 版本时候那样移除特殊字符外,还会将配置均以全小写的方式进行匹配和加载。所以,下面的 4 种配置方式都是等价的:
- properties 格式:
spring.jpa.databaseplatform=mysql
spring.jpa.database-platform=mysql
spring.jpa.databasePlatform=mysql
spring.JPA.database_platform=mysql
- yaml 格式:
spring:
jpa:
databaseplatform: mysql
database-platform: mysql
databasePlatform: mysql
database_platform: mysql
推荐使用全小写配合-分隔符的方式来配置,比如:spring.jpa.database-platform=mysql;在 properties 文件中使用 []
来定位列表类型,比如:
spring.my-example.url[0]=http://example.com
spring.my-example.url[1]=http://spring.io
也支持使用逗号分割的配置方式,上面与下面的配置是等价的:
spring.my-example.url=http://example.com,http://spring.io
而在 yaml 文件中使用可以使用如下配置:
spring:
my-example:
url:
- http://example.com
- http://spring.io
也支持逗号分割的方式:
spring:
my-example:
url: http://example.com, http://spring.io
注意:在 Spring Boot 2.0 中对于 List 类型的配置必须是连续的,不然会抛出 UnboundConfigurationPropertiesException 异常,所以如下配置是不允许的:
foo[0]=a
foo[2]=b
在 Spring Boot 1.x 中上述配置是可以的,foo[1]由于没有配置,它的值会是 null。Map 类型在 properties 和 yaml 中的标准配置方式如下:
- properties 格式:
spring.my-example.foo=bar
spring.my-example.hello=world
- yaml 格式:
spring:
my-example:
foo: bar
hello: world
注意:如果 Map 类型的 key 包含非字母数字和-
的字符,需要用[]
括起来,比如:
spring:
my-example:
'[foo.baz]': bar
嵌入属性
Spring 也较好地支持了对于嵌入属性的处理,譬如:
public class Credentials {
private String authMethod;
private String username;
private String password;
// standard getters and setters
}
public class ConfigProperties {
private String host;
private int port;
private String from;
private List<String> defaultRecipients;
private Map<String, String> additionalHeaders;
private Credentials credentials;
// standard getters and setters
}
其对应的属性文件如下:
#Simple properties
mail.hostname=mailer@mail.com
mail.port=9000
mail.from=mailer@mail.com
#List properties
mail.defaultRecipients[0]=admin@mail.com
mail.defaultRecipients[1]=owner@mail.com
#Map Properties
mail.additionalHeaders.redelivery=true
mail.additionalHeaders.secure=true
#Object properties
mail.credentials.username=john
mail.credentials.password=password
mail.credentials.authMethod=SHA1
参数引用
在 application.properties 中的各个参数之间,我们也可以直接通过使用 PlaceHolder 的方式来进行引用,就像下面的设置:
book.name=xxx
book.author=xxx
book.desc=${book.author} is writing《${book.name}》
book.desc 参数引用了上文中定义的 book.name 和 book.author 属性,最后该属性的值就是 xxx is writing《xxx》。当 Docker 启动 SpringBoot 打包的服务时,且一些参数需要从外界获取而非写死在 properties 文件里,通过以下两步完成此需求:
- 在配置文件中配置环境变量
spring.redis.host=${REDIS_HOST:127.0.0.1}
spring.redis.port=6379
spring.redis.timeout=30000
以上表示 REDIS_HOST 在系统环境变量中获取,如果获取不到默认值为 127.0.0.1。
- 在启动 Docker 容器时传入环境参数
$ docker run -d --name test2 {镜像名} -e REDIS_HOST=192.168.0.1
使用随机数
在一些特殊情况下,有些参数我们希望它每次加载的时候不是一个固定的值,比如:密钥、服务端口等。在 Spring Boot 的属性配置文件中,我们可以通过使用 ${random}
配置来产生随机的 int 值、long 值或者 string 字符串,这样我们就可以容易的通过配置来属性的随机生成,而不是在程序中通过编码来实现这些逻辑。${random}
的配置方式主要有一下几种,读者可作为参考使用。
# 随机字符串
com.didispace.blog.value=${random.value}
# 随机int
com.didispace.blog.number=${random.int}
# 随机long
com.didispace.blog.bignumber=${random.long}
# 10以内的随机数
com.didispace.blog.test1=${random.int(10)}
# 10-20的随机数
com.didispace.blog.test2=${random.int[10,20]}
Properties
properties 文件大家经常用,这里就简单介绍一下。其语法结构形如:key=value。注意中文乱码问题,需要转码成 ASCII。具体如下所示:
userinfo.account=wx
userinfo.age=25
userinfo.active=true
userinfo.created-date=2018/03/31 16:54:30
userinfo.map.k1=v1
userinfo.map.k2=v2
userinfo.list=one,two,three
userinfo.position.name=Test
userinfo.position.salary=19999.99
在 properties 文件中使用 [] 来定位列表类型,比如:
spring.my-example.url[0]=http://example.com
spring.my-example.url[1]=http://spring.io"
也支持使用逗号分割的配置方式,上面与下面的配置是等价的:
spring.my-example.url=http://example.com,http://spring.io
在 Spring Boot 2.0 中对于 List 类型的配置必须是连续的,不然会抛出 UnboundConfigurationPropertiesException 异常。