一、Spring Boot 配置文件
Spring Boot使用一个全局配置文件application.properties,也可以使用yml格式,配置文件默认放在在resources目录下,代码中指定配置文件时指定的方式为”classpath:application.properties“。使用IDEA创建Spring Boot项目默认的配置文件是properties格式。
Spring Boot的全局配置文件可以对默认配置进行修改。
二、YMAL 配置文件
新建项目spring-boot-configuration,导入基本的Web依赖及Lombok依赖,将application.properties配置文件改为application.yml;并新建entity包,增加Person和Dog实体类
@Data public class Person { private String lastName; private Integer age; private Boolean boss; private Date birth; private Map<String,Object> maps; private List<Object> list; private Dog dog; } 复制代码
@Data public class Dog { private String name; private Integer age; } 复制代码
2.1 - YAML配置文件基本语法
YAML基本语法
YAML基本语法规则如下:
- 使用缩进表示层级关系
- 缩进时不允许使用Tab键,只允许使用空格
- 缩进的空格数量不重要,只要相同层级的元素左侧对其即可
- 大小写敏感
YAML支持的数据结构有:
- 对象:键值对的集合
- 数组:一组按次序排列的值
- 字面量:单个的、不可分割的值
YAML的格式是k: v格式, 表示一对键值对(冒号后面必须有空格),以空格的缩进来控制层级关系,只要是做对齐的一列数据,都认为是同一层级。如yml中对应用访问端口的配置
server: port: 8081 path: / 复制代码
这里就是通过缩进来表示层级关系,path和port为同一层级,yml文件中属性和值是大小写敏感的。
YAML配置文件中支持的数据类型
字面量:既普通值,包括数字、字符串、布尔值(true和false)
格式为key: value格式, 字面值直接写,字符串默认不用加上单引号或者双引号。
单引号和双引号在yml配置文件中是有区别的
- ”“:双引号不会转义特殊字符,特殊字符会作为本身想表示的作用,
- 如name: "zhangsan\nlisi", 输出 张三 换行 lisi
- ‘’: 单引号会转义字符串,特殊字符串最终只是一个普通的字符串数据
- 如name: 'zhangsan \n lisi', 输出 zhangsan \n lisi
对象及Map(属性和值/键值对)
格式为key: value,在对象名称的下一行以k: v的形式写上属性名和value 对象具体属性名和属性值的书写格式还是还是k: v格式
friend: # 对象名 # 对象包含的属性名和属性值 lastName: zhangsan # 属性名: 属性值 age: 30 复制代码
另外一种写法是行内写法,既使用{}来包括属性名和属性值的k: v。
friend:{lastName: zhangsan, age: 18} 复制代码
数组(List,Set),用 -value 表示数组中的一个元素
# 数组或者集合名 pets: # 集合中包含的元素 - cat - dog - pig 复制代码
也可以使用[],value之间使用“,”隔开
pets: [cat,dog,pig] 复制代码
复合结构,既包含了对象、数组、字符串等各种形式的数据
使用YML配置文件给Person对象属性赋值
将resources目录下的application.properties重命名为application.yml,使用yml来给Person对象赋值,并导入配置文件处理依赖,书写配置文件时IDEA会有提示
<!--导入配置文件处理器--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> 复制代码
application.yml配置文件内容为
# 对象名 person: # 属性名: 属性值 lastN-name: stark age: 40 boss: true birth: 1970/12/12 maps: {k1: v1, k2: v2} list: - l1 - l2 - l3 - l4 dog: name: pipi age: 2 复制代码
将YML配置文件中的属性值映射的Person对象中需要使用到@ConfigurationProperties注解,这个注解将标注类和注解中指定的配置进行绑定(默认指定的配置文件是application.yml), 注解中prefix属性表示配置的前缀,将这个前缀下的配置与Person对象中的属性进行一一映射
还需要使用@Component注解将该类加入到Spring容器中,并且必须是容器中组件才能使用@ConfigurationProperties注解,从容器中获取Person对象并输出,查看是否赋值成功
在Person实体类上增加注解
@ConfigurationProperties(prefix = "person") @Component @Data public class Person { // 中间内容不变 } 复制代码
在test包下新增测试类PersonTest
@SpringBootTest public class PersonTest { @Autowired private Person person; @Test public void testPerson(){ System.out.println(person); } } 复制代码
执行测试
控制台输出Person对象,属性被成功赋值
利用properties文件配置给对象赋值
person.last-name=stark1 person.age=19 person.birth=1980/12/12 person.boss=true person.maps.k1=v1 person.maps.k2=v2 person.list=a,b,c person.dog.name=pipi person.dog.age=2 复制代码
注释yml文件中的配置,执行测试
同样可以成功给Person的属性赋值。
当yml和properties两种格式的配置文件同时存在时yml格式优先级更高
使用@Value注解给属性赋值
除了@ConfigurationProperties注解来指定配置前缀进行赋值,还可以使用@Value注解来指定配置和属性一一绑定。@Value注解的作用与Spring XML配置文件中bean标签下的property的value属性的作用是一致的,主要用来给属性赋值。
在Person中实体类属性上使用@Value注解
//@ConfigurationProperties(prefix = "person") @Component @Data public class Person { @Value("${person.last-name}") private String lastName; @Value("#{10*2}") private Integer age; @Value("true") private Boolean boss; // 其余内容不变 } 复制代码
修改application.yml中配置文件内容为
person: last-name: stark 复制代码
执行PersonTest测试
同样可以将Person实体类的lastName属性与配置文件中的配置绑定成功,根据输出@Value还支持一些表达式。
@Value只支持取出基本类型数据,在Person实体类的maps属性上使用@Value注解来获取配置文件中的数据
@Value("${person.maps}") private Map<String,Object> maps; 复制代码
修改application.yml配置文件
# .... maps: {k1: v1, k2: v2} list: - l1 - l2 - l3 - l4 dog: name: pipi age: 2 复制代码
执行测试
Person对象的maps属性赋值失败。
@Value VS @ConfigurationProperties
@ConfigurationProperties | @Value | |
功能 | 批量注入配置文件中的属性值 | 逐个指定属性所对应的值 |
松散绑定语法 | 支持 | 不支持 |
SpEL表达式 | 不支持 | 支持 |
JSR303数据校验 | 支持 | 不支持 |
复杂类型封装 | 支持 | 不支持 |
松散绑定不支持测试
person: last-name: stark 复制代码
@Value("${person.lastName}") private String lastName; 复制代码
执行测试
@Value("${person.lastName}")中的${person.lastName}无法和配置文件中的person.last-name一一绑定
plus:属性名匹配规则,以Person实体类的lastName属性为例,在配置文件中可以写成以下几种形式
- person.lastName:与属性名一致
- person.last-name:使用 - 连接,并将大写改为小写
- person.last_name:使用 _ 连接,并将首字母大写改为小写
数据校验不支持测试
Spring Boot 在2.3 版本之后 Web Staters中不再包含validation,查看官方文档Validation Starter no longer included in web starters,如果需要使用validation,导入以下依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> 复制代码
在Person实体类的lastName属性上增加@Email注解,校验是否为合法的email地址
//@ConfigurationProperties(prefix = "person") //@PropertySource(value = {"classpath:person.properties"}) @Component @Data @Validated public class Person { @Email @Value("${person.last-name}") private String lastName; // 其余内容不变 } 复制代码
控制台成功输出person对象,说明@Email注解并未生效
@ConfigurationProperties(prefix = "person") //@PropertySource(value = {"classpath:person.properties"}) @Component @Data @Validated public class Person { @Email // @Value("${person.last-name}") private String lastName; // 其余内容不变 } 复制代码
再次执行PersonTest
控制台输出“不是一个合法的电子邮件地址”,成功执行了校验
@Value与@ConfigurationProperties如何选择?
如果只是在业务逻辑中获取配置文件中某一项配置的值,建议使用@Value,如果有一个实体类和配置文件进行映射时建议使用@ConfigurationProperties
使用@Value注解的简单例子
增加HelloController
@RestController public class HelloController { @Value("${person.last-name}") private String name; @RequestMapping("/hi") public String hi(){ return "Hi, " + name; } } 复制代码
重启启动应用