一、SpringBoot 的配置文件
SpringBoot 在底层都给我们自动配置好了一些属性值,我们可以通过配置 SpringBoot 的配置文件修改 SpringBoot 自动配置的默认值。SpringBoot 使用一个全局的配置文件,配置文件名是固定的;
- application.properties
- application.yml
SpringBoot 的配置文件一般放在 src/main/resources
目录下。
二、什么是 YAML
文件后缀为 yml 是 YAML 语言的文件,YAML(YAML Ain't Markup Language)是一个标记语言,以数据为中心,比 JSON、XML 等更适合做配置文件。
YAML 的写法
server:
port: 8081
XML 的写法
<server>
<port>8081</port>
</server>
1、语法规则
- 使用缩紧表示层级关系
- 缩紧时只能使用空格,不能使用 tab 键
- 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
- 大小写敏感
2、数据结构
- 对象:键值对的集合(map)。
- 数组:一组按次序排列的值(list、set)。
- 字面量:单个的、不可再分的值。
3、简单写法
k:(空格)v,表示一对键值对;以空格的缩进来控制层级关系,只要是左对齐的一列数据,都是同一个层级的(属性和值也是大小写敏感)。
server:
port: 8081
servlet:
context-path: /hello
4、值的写法
字面量:普通的值(数字,字符串,布尔)
k: v 字面量直接来写,字符串默认不用加上单引号或者双引号。
- 加"(双引号):会转义字符串里面的特殊字符;特殊字符会作用本身想表示的意思。
- 加'(单引号):不会转义特殊字符,特殊字符最终只是一个普通的字符串数据。
对象(属性和值)、Map(键值对)
k: v: 在下一行来写对象得到属性和值的关系,注意缩进,对象还是 k: v 方式。
friends:
lastName: zyxwmj.top
age: 20
单行写法:
friends: {lastName: zhangsan,age: 18}
数组,List,Set
用 -值 表示数组中的一个元素
pets:
- cat
- dog
- pig
单行写法:
pets: [cat,dog,pig]
总结
person:
lastName: hello
age: 18
boss: false
# 时间类型
date: 2017/12/12
array:
- 3
- 2
list:
- lisi
- zhaoliu
set:
- lisi
- zhaoliu
map: {k1: v1, k2: v2}
dog:
name: 小狗
age: 10
三、属性注入
在实际开发中,我们为了方便管理项目中的常量或配置。常常将这些配置写入到配置文件中,在项目运行时,将配置注入到配置类中。
为了方便我们编写配置文件,导入 SpringBoot 提供的配置文件处理,配置文件进行绑定后就会有提示。在 pom.xml 文件中导入以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
1、@ConfigurationProperties
@ConfigurationProperties
注解可以将配置文件中的属性进行映射,注入到配置类中。
例如,我们在配置文件中写入以下配置:
dog:
name: 小狗
age: 10
创建一个实体类,加上 @Component
注解,将当前类注入到 IOC
容器中。然后通过 @ConfigurationProperties
注解的 prefix
的属性值与配置文件的配置进行绑定。
注意: 类中成员变量的值必须与配置文件中的键对应,且类中必须有 Set 方法,否则无法注入进去。
/**
* @Component 把当前类注入到容器中
* @ConfigurationProperties 的 prefix值 和配置文件的对应,其他名字只有相同才能注入进去,必须有 set 方法
*/
@Component
@ConfigurationProperties(prefix = "dog")
public class Dog {
String name;
int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
使用 @ConfigurationProperties 注入 person
注入上面 YML 中配置的 person。
@Component
@ConfigurationProperties(prefix = "person")
public class Person {
String lastName;
int age;
boolean boss;
Date date;
int[] array;
List<String> list;
Set<String> set;
Map<String, String> map;
Dog dog;
@Override
public String toString() {
return "Person{" +
"lastName='" + lastName + '\'' +
", age=" + age +
", boss=" + boss +
", date=" + date +
", array=" + Arrays.toString(array) +
", list=" + list +
", set=" + set +
", map=" + map +
", dog=" + dog +
'}';
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public void setAge(int age) {
this.age = age;
}
public void setBoss(boolean boss) {
this.boss = boss;
}
public void setDate(Date date) {
this.date = date;
}
public void setArray(int[] array) {
this.array = array;
}
public void setList(List<String> list) {
this.list = list;
}
public void setSet(Set<String> set) {
this.set = set;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setDog(Dog dog) {
this.dog = dog;
}
}
2、快速测试
通过 SpringBoot 提供的单元测试,可以快速进行测试属性值是否注入到了类中。
@SpringBootTest
public class JournalApplicationTests {
@Autowired
Dog dog;
@Test
public void demo() {
System.out.println(dog);
}
}
3、@Value
通过 @Value
注解可以为单个成员变量注入值,首先通过 @Component
注解,将当前类注入到 IOC
容器中。
@Component
public class Dog {
@Value("${dog.name}")
String name;
@Value("${dog.age}")
int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
4、@Validation
使用 @Validation
+ @ConfigurationProperties
注解可以对注入的属性值进行限制(JSR303 数据效验),例如,使用 @Email
可以限制注入的属性格式必须为邮箱,否则会报错。
@Component
@Validated
@ConfigurationProperties(prefix = "dog")
public class Dog {
/**
* @Email 注解
* name 必须是邮箱格式,否则报错
*/
@Email
String name;
int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
5、@ConfigurationProperties 和 @Value 的异同
| | ConfigurationProperties | @Value |
| - | - | - |
| 功能 | 批量注入配置文件中的属性 | 单个注入 |
| 松散绑定(松散语法) | 支持 | 不支持 |
| SpEL | 不支持 | 支持 |
| JSR303 数据效验 | 支持 | 不支持 |
| 复杂类型封装(map...) | 支持 | 不支持 |
属性名匹配规则(松散语法)
- person.firstName:使用标准方式
- person.first-name:大写用-
- person.first_name:小写用_
- PERSON_FIRST_NAME:推荐系统属性使用这种写法
总结
- 配置文件 yml 还是 properties 它们都能获取到值。
- 如果我们只是需要获取一下配置文件中某项值,使用@Value
- 如果我们专门编写了一个 javaBean 来和配置文件进行映射,我们就直接使用@ConfigurationProperties
6、Environment
业务开发中可能需要根据当前环境来读取配置,比如:在 Windows 系统中读取哪些配置;在 Linux 系统中读取哪些配置。这个时候可以使用 Environment 类。
注入 Environment:
@Resource
private Environment environment;
获取配置文件中的指定值(其他用法不在展示):
environment.getProperty("ras.key.window.privateFilePath");
四、配置文件占位符
1、随机数
| 占位符 | 作用 |
| - | - |
| ${random.value} | 生成随机字符串 |
| ${random.uuid} | 生成唯一序列 |
| ${random.int} | 生成随机数字,最值为长度为int |
| ${random.long} | 生成随机数字,最值为长度为long |
| ${random.int(10)} | 生成随机数字,最值为长度为10 |
2、获取之前的配置
通过占位符获取之前配置的值,如果没有可以使用 :默认值
指定默认值,例如如下,name的值为 小狗10
。
dog:
name: 小狗${dog.age:666}
age: 10
五、注入外部配置文件
使用 @propertySource
和 @ImportResource
注解来引用外部配置文件。
1、@propertySource
@ConfigurationProperties
和 @Value
注解默认是在 SpringBoot 的主配置文件中查找配置项,我们也可以使用外部配置文件,进行参数注入。使用 @propertySource
加载指定的配置文件(只能是 properties 文件)。首相创建一个名为 config.properties
的配置文件,内容如下:
dog.name= 小狗
dog.age= 18
然后使用 @propertySource
注解,通过 value
属性值指定配置文件的位置即可。
@PropertySource(value = "classpath:config.properties")
@ConfigurationProperties(prefix = "dog")
@Component
public class Dog {
String name;
int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
properties 文件乱码
如果将 properties
文件中的汉字注入到实体类中出现乱码的话,修改 idea 的配置即可。
2、@ImportResource
SpringBoot 里面没有 Spring 的配置文件,我们自己编写的配置文件,也不能自动识别,想让 Spring 的配置文件生效,我们可以使用 @ImportResource
注解。
首先我们使用传统 Spring 的方式将类注入到容器中。
<?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="helloService" class="top.zyxwmj.journal.controller.HelloService"/>
</beans>
测试
我们通过 ApplicationContext
类的 containsBean
方法判断指定组件是否注入到了容器中。
@SpringBootTest
public class JournalApplicationTests {
@Autowired
ApplicationContext ioc;
@Test
void contextLoads() {
// 判断ioc中是否有指定组件
System.out.println(ioc.containsBean("helloService"));
}
}
测试结果为 false
,因为我们的 Spring 的配置文件并没有和 SpringBoot 进行关联。我们在 SpringBoot 的启动类上加 @ImportResource
注解,指向 Spring 的配置文件即可。
@ImportResource(locations = {"classpath:beans.xml"})
@SpringBootApplication
public class JournalApplication {
public static void main(String[] args) {
SpringApplication.run(JournalApplication.class, args);
}
}
3、@Configuration 和 @Bean
在实际开发中,我们不编写 Spring 的配置文件。SpringBoot 推荐使用容器中添加组件的方式,推荐使用全注解方式,例如:
/**
* @Configuration 告诉 SpringBoot 这是一个配置类
*/
@Configuration
public class MyConfig {
/**
* 将方法的返回值添加到容器中,容器中这个组件默认的id就是方法名
*/
@Bean
public HelloService helloService() {
return new HelloService();
}
}
标题:SpringBoot 配置值的注入和YML的编写
作者:Yi-Xing
地址:http://47.94.239.232/articles/2020/03/29/1585470511417.html
博客中若有不恰当的地方,请您一定要告诉我。前路崎岖,望我们可以互相帮助,并肩前行!