概述
这一篇主要介绍下SpringBoot配置相关的内容。
通过配置文件,我们可以做到如下事情:
- 修改springboot的默认配置项
- 添加自定义配置项
SpringBoot使用全局的配置文件,主配置文件名是固定的:application.xxx
springboot的配置文件有多种格式可选,如:.properties,.xml,.yml。
我个人比较喜欢yaml的简洁,所以推荐使用yaml。
yaml的基本语法
下面介绍些yaml的语法
- 使用空格缩进来表示结构,相同层级的数据其缩进的长度必定相同:
1 2 3 4 5 6 |
worker1: name: robin age: 27 worker2: name: jane age: 22 |
- 支持使用注解,但只支持使用单行注解,注解以“#”号开头:
1 2 3 |
worker1: # a worker object name: robin age: 27 |
- 支持直接类型或字符串的列表或数组结构,有两种表达形式:
- 每个列表成员占一行,以横杠和空格(- )开头
- 所有列表成员在同一行,被方括号([])包围,列表成员间以逗号和空格分隔
1 2 3 4 |
whiteUrl: - www.chobit.org - www.zhyea.com blackUrl: [www.black.com, www.forbidden.com] |
- 也支持Map结构,同样也有两种表达形式:
- 每个KV对占一行,键值用冒号分隔
- 所有KV对在同一行,被大括号({})包围, KV对之间用逗号和空格分隔,键值用冒号分隔
1 2 3 4 |
worker1: # a worker object name: robin age: 27 worker2: {name: jane, age: 22} # another worker object |
- 通常字符串不需要使用引号,但必要时可以使用单引号(’)或双引号(”),比如需要使用转义字符时
1 |
content: 'line \n next line' |
- 可以使用两个叹号(!!)来强制指定格式(这个感觉用处不大,但是万一用到了呢)
1 2 |
id: !!int 128 seq: !!str 11112222 |
- 内容可以重复使用,原始位置的内容用(&标记名)来标记,在引用位置用(*标记名)来引用
1 2 3 4 |
worker1: &robin # a worker object name: robin age: 27 worker3: *robin |
- 如果想在一个文件里面配置不同的profile,可以使用三个横杠“—”将yaml文件分割成多个独立区域,每个区域被视为一个独立的文件。三个点号“…”用来标识文件结尾。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
server: port: 8081 spring: profiles: active: test # 切换配置 --- # 开发环境 spring: profiles: dev --- # 测试环境 spring: profiles: test --- # 生产环境 spring: profiles: prod |
如示例代码,在一个yaml文件中存在多个独立区域时,使用spring.profiles属性来标识配置区域的profile信息。
多环境配置
在主配置文件application.yml之外,还可以有多个外部配置文件,其名称格式固定为application-{profile}.yml。
SpringBoot会根据主配置文件中的spring.profiles.active参数来决定加载哪个配置文件。
通过这种方式SpringBoot实现了支持多环境配置,从而能够在不同环境下(开发、测试、生产)进行配置参数的切换。
主配置文件中的spring.profiles.active属性还可以有多个值,每个值以逗号进行分割:
1 2 3 |
spring: profiles: active: dev,test |
这种方式允许我们为不同需求创建不同的配置文件。SpringBoot会依序加载每个值指向的配置文件。
配置文件的加载顺序是主配置文件application.yml,spring.profiles.active指定的外部配置文件。如有冲突项,后面加载的配置会覆盖前面的。
如果多个外部配置文件有相同的配置项,建议在主配置文件中进行配置。
如spring.profiles.active指定的值无法与任何外部文件匹配,SpringBoot会尝试加载application-default.yml文件。
结合@Profile实现内部实例的动态选择
spring.profiles.active参数不仅可以指明要使用哪个外部配置文件,也可以控制内部实例的选择。这需要通过配合@Profile
注解实现。
如下例:
1 2 3 4 5 6 7 8 9 10 11 |
@Profile("prod") @Bean public Worker tom() { return new Worker("Tom", 8); } @Profile("dev") @Bean public Worker jim() { return new Worker("Jim", 8); } |
如果没有@Profile
注解,在启动的时候SpringBoot就会报错,因为为一个Worker类提供了两个实例。但是现在,SpringBoot可以根据spring.profiles.active指明的profile和@Profile
注解来选择注入哪个实例。
@Profile
注解可以用于含有@Component
、@Configuration
、@Bean
等注解的类及其方法。
@Profile
注解也可以有多个值,如下:
1 2 3 4 5 |
@Profile({"dev", "test"}) @Bean public Worker jim() { return new Worker("Jim", 8); } |
这样,在profile是dev或test时,这个Bean都可以被成功注入。
配置项获取
使用SpringBoot的配置项有两种方式:通过@Value
注解或通过@ConfigurationProperties
注解。这两种方式各有长处,可根据进行选择。
通过@Value注解获取
@Value
注解适用于单个配置项的获取,比如我们可以获取当前的外部配置文件的profile:
1 2 |
@Value("${spring.profiles.active}") private String profile; |
@Value
注解的一个优势是可以使用SPEL表达式(关于SPEL表达式,我有整理过:《SpringBoot SpEL表达式》),如下是一个非常粗略的SPEL表达式:
1 2 3 4 |
@Value("#{'token:' + '${custom.token}'}") private String token; //输出结果为:token:zhyeeeeeeee |
@Value
注解的不足之处在于只能获取直接类型的值或字符串,不能映射为复杂类型。
通过@PropertiesConfiguration注解获取
@PropertiesConfiguration
注解的主要特点是可以将配置映射为对象。因此平时还是通过这种方式获取SpringBoot配置为主。
@PropertiesConfiguration
注解可应用于类或成员方法。
如下是将应用于类的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
@Component @ConfigurationProperties(prefix = "custom") public class CustomConfig { private int id; private String token; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getToken() { return token; } public void setToken(String token) { this.token = token; } } |
从示例代码中可以看到配置类需要有@Component
注解或@Configuration
注解,以便完成注入。
此外,在使用@ConfigurationProperties
注解的时候需要传入注入配置属性的前缀,以便获得配置项的范围。
在成员方法上使用@PropertiesConfiguration
注解则是一种更为灵活的方式,能够充分弥补@Value
注解的不足,示例如下:
1 2 3 4 5 |
@Bean @ConfigurationProperties(prefix = "custom.worker") private Worker getWorker() { return new Worker(); } |
注意这里还需要用到@Bean
注解,以便将读取到的配置信息注入到实例上。不过不能通过getWorker()方法调用,否则获取的还是一个只有默认值的对象。要使用该实例还是需要通过@Autowired
注解来注入。
最后,可以看下我在GITHUB上的示例应用,在里面我尝试了SpringBoot配置的各种应用实践。
就这样。
发表评论