配置方式
配置文件
SpringBoot使用一个全局的配置文件: application.properties或application.yml(或yaml),其中文件名是固定的。
YAML文件配置
以往的配置文件大多都是xml文件,而YAML则是以数据为中心,比json,xml等更适合做配置文件。
语法
以空格的缩进来控制层级关系(空格多少皆可),只要是左对齐的一列数据,都是同一个层级的。 数据的格式是k: v,需要注意冒号 和值中间是有一个空格的,并且属性和值区分大小写。
server:
port: 8081
path: /hello
值的写法
(1)值可以是数字,字符串,布尔,且字符串默认不用加单/双引号。 如果加上单/双引号,例如:
name: "zhangsan \n lisi"
在双引号里 特殊字符会作为本身想表示的意思,因此会输出zhangsan,然后换行,再输出 lisi
name: ‘zhangsan \n lisi’:输出;zhangsan \n lisi
在单引号里特殊字符只是一个普通的字符串数据,因此输出 zhangsan \n lisi
(2)值还可以作为对象,例如:
friends:
lastName: zhangsan
age: 20
此外还可以写成一行:
friends: {lastName: zhangsan,age: 20}
(3)值也可以作为数组里的一个元素
pets:
- cat
- dog
- pig
同样也可写成一行:
pets: [cat,dog,pig]
配置文件值注入
导入依赖:
<!--导入配置文件处理器,配置文件进行绑定就会有提示-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
配置文件application.yml:
person:
lastName: on1
age: 20
isStu: false
birth: 2019/02/15
maps: {k1: v1, k2: 12}
list:
- C2y
- sngu
cat:
name: 小猫
age: 2
bean类:
/*
@ConfigurationProperties注解将本类中所有属性与配置文件中相关的配置进行绑定
prefix属性表示与配置文件中哪个属性对应
加上@Component表示该组件是容器里的组件,这样才能使用容器提供的ConfigurationProperties
*/
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
private String lastName;
private Integer age;
private Boolean isStu;
private Date birth;
private Map<String, Object> maps;
private List<Object> list;
private Cat cat;
//省略get / set,toString方法
}
public class Cat {
private String name;
private Integer age;
//省略get / set,toString方法
}
测试:
@RunWith(SpringRunner.class)
@SpringBootTest
class HaloworldQuickstartApplicationTests {
@Autowired
Person person;
@Test
void contextLoads() {
System.out.println(person);
}
}
properties文件配置
person.last-name=张三
person.age=18
person.birth=2017/02/15
person.is-stu=false
person.maps.k1=v1
person.maps.k2=15
person.list=a,b,c
person.cat.name=cat
person.cat.age=3
通过下图将配置文件字符集改为UTF-8来解决中文乱码:

控制台输出:

@Value注解
前面的例子我们使用的是@ConfigurationProperties注解将本类中所有属性与配置文件中相关的配置进行绑定,除此之外还可以使用@value注解来一个个的指定属性值。
@Component
public class Person {
@Value("${person.last-name}")
private String lastName;
@Value("#{3 * 2}")
private Integer age;
@Value("true")
private Boolean isStu;
//省略其他属性和get/set,toString方法
}
@ConfigurationProperties和@Value的对比
(1)@ConfigurationProperties是批量注入配置文件中的属性,而@Value是一个个注入
(2)@ConfigurationProperties支持松散绑定,而@Value不支持
在说明松散绑定前先介绍一下属性名匹配规则:
- person.first-name:该写法表示-后面的字母是大写
- person.first_name:该写法表示_后面的字母是大写
- person.firstname:标准写法
- PERSON_FIRST_NAME:推荐系统属性使用该写法
如果上例中的注入属性lastName的写法改为:
@Value("${person.lastName}")
则会报错,而如果是@ConfigurationProperties配置的类,则将配置文件的属性赋值改为:
person.lastName=张三
也是可以的。
(3)@ConfigurationProperties不支持SpEl,而@Value支持
上例中@Value注解可以是这种写法:
@Value("#{3 * 2}")
但如果是@ConfigurationProperties注解,则不允许,如果在配置文件中
(4)@ConfigurationProperties支持JSR303数据校验,而@Value不支持
比如此处我们使用@Max注解来检验配置文件中的age是否是大于33的,若是则会报错。
@Component
@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
private String lastName;
@Max(33)
private Integer age;
//...
}

@Component
//@ConfigurationProperties(prefix = "person")
@Validated
public class Person {
@Value("${person.lastName}")
private String lastName;
@Value("${person.age}")
@Max(33)
private Integer age;
//...
}

(5)@ConfigurationProperties支持复杂类型封装,而@Value不支持
比如上例中使用
@Value("${person.maps}")
private Map<String, Object> maps;
则会报错,@Value只支持一些基本类型,list、数组的封装。
总结来说,如果我们只是在某个业务逻辑中获取一下配置文件中的某项值,则使用@Value,如下例所示。
@RestController
public class HaloController {
@Value("${person.lastName}")
private String name;
@RequestMapping("/halo")
public String hello() {
return "hello " + name;
}
}
如果是有一个专门的javaBean类和配置文件映射,则使用@ConfigurationProperties
@PropertySource注解
除了将属性值放在application.properties和application.yml外,我们还可以在resources文件夹下单独写一个person.properties作为映射文件。此时我们就需要@PropertySource注解来指定文件名。
示例
@Component
@PropertySource(value = {"classpath:person.properties"})
@ConfigurationProperties(prefix = "person")
public class Person {
//...
}
person.lastName=呱呱
person.age=35
person.birth=2017/02/15
person.is-stu=false
person.maps.k1=v1
person.maps.k2=15
person.list=a,b,c
person.cat.name=cat
person.cat.age=3
然后将application.properties里的person类映射注释掉,即可成功映射。

该注解仅支持properties文件,不支持yaml文件
相关注解
@ImportResource注解
SpringBoot里没有Spring配置文件,它不会自动识别我们自己编写的配置文件,因此我们需要通过注解来加载我们写的Spring配置文件。
示例
比如我们在resources下写一个Spring配置文件并定义一个bean:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="HaloService" class="com.on1.haloworldquickstart.HaloService">
</bean>
</beans>
在主配置类下通过注解@ImportResource声明Spring文件名
@ImportResource(locations = {"classpath:beans.xml"})
@SpringBootApplication
public class HaloworldQuickstartApplication {
public static void main(String[] args) {
SpringApplication.run(HaloworldQuickstartApplication.class, args);
}
}
测试一下,输出为true。
@RunWith(SpringRunner.class)
@SpringBootTest
public class HaloworldQuickstartApplicationTests {
@Autowired
Person person;
@Autowired
ApplicationContext ioc;
@Test
public void ifHasBean() {
System.out.println(ioc.containsBean("helloService"));
}
}
@Bean
上述通过注解的方式来加载Spring文件过于麻烦,SpringBoot推荐通过配置类代替配置文件的方式来向容器里注入组件,即使用全注解的方式。
示例
package com.on1.haloworldquickstart.service;
public class HelloService {
}
将上例的@ImportResource注解删掉,创建一个配置类(也可以在主配置类里操作):
@Configuration
public class MyAppConfig {
// 将返回类型对象添加到容器里,组件的id值默认是方法名
@Bean
public HelloService helloService() {
System.out.println("正在向容器里添加组件");
return new HelloService();
}
}
测试一下,输出为true。
@RunWith(SpringRunner.class)
@SpringBootTest
class HaloworldQuickstartApplicationTests {
@Autowired
ApplicationContext ioc;
@Test
void ifHasBean() {
System.out.println(ioc.containsBean("helloService"));
}
}
配置文件的相关事项
配置文件占位符
我们可以在映射文件里 使用随机数:
person.lastName=张三 ${random.uuid}
person.age=${random.int}
person.birth=2017/02/15
person.is-stu=false
person.maps.k1=v1
person.maps.k2=15
person.list=a,b,c
person.cat.name=${person.lastName}_cat
person.cat.age=3
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
//属性值与上例一样
}
测试方法
@Test
void contextLoads() {
System.out.println(person);
}
输出:

此例person.cat.name获取了前面配置的属性值person.lastName,如果获取的属性值不存在,则我们可以指定默认值,如下例的person.halo。
person.cat.name=${person.halo:halo}_cat
输出:

Profile
Profile是Spring对不同环境提供不同配置功能的支持,可以通过激活、指定参数等方式快速切换环境
properties文件的分支配置
文件名格式为:application-{分支名}.properties,比如此处我们命名为application-dev.properties,该文件内容为:
server.port=8082
程序默认加载主配置文件application.properties,因此我们需要在指定加载哪个配置文件:
spring.profiles.active=dev
运行后端口号变为8082:

yml文件的分支配置
注释掉前面的指定:spring.profiles.active=dev
在application.yml
# 通过spring.profiles.active指定是哪个分区的环境
spring:
profiles:
active: dev
---
server:
port: 8083
spring:
profiles: dev
---
server:
port: 8085
spring:
profiles: prod
---
运行后即可发现端口号为dev分区的端口号8083:

(2)此外还可以在Program arguments中指定分区名

运行后即可发现端口号为prod分区的端口号8085:

默认配置文件加载顺序
SpringBoot启动会按以下顺序来扫描application.properties/yml文件作为默认配置文件。如下图所示:优先级低的先配置,高优先级的配置会覆盖低优先级的配置,并且是互补配置。
- 项目文件下的某一文件里的application.properties/yml配置文件
- 项目文件下里的application.properties/yml配置文件
- resources文件里某一文件下的application.properties/yml配置文件
- resources文件里的application.properties/yml配置文件
