一、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 的写法

1server:
2    port: 8081

XML 的写法

1<server>
2    <port>8081</port>
3</server>

1、语法规则

  • 使用缩紧表示层级关系
  • 缩紧时只能使用空格,不能使用 tab 键
  • 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
  • 大小写敏感

2、数据结构

  • 对象:键值对的集合(map)。
  • 数组:一组按次序排列的值(list、set)。
  • 字面量:单个的、不可再分的值。

3、简单写法

  k:(空格)v,表示一对键值对;以空格的缩进来控制层级关系,只要是左对齐的一列数据,都是同一个层级的(属性和值也是大小写敏感)。

1server:
2  port: 8081
3  servlet:
4    context-path: /hello

4、值的写法

字面量:普通的值(数字,字符串,布尔)

  k: v 字面量直接来写,字符串默认不用加上单引号或者双引号。

  • 加"(双引号):会转义字符串里面的特殊字符;特殊字符会作用本身想表示的意思。
  • 加'(单引号):不会转义特殊字符,特殊字符最终只是一个普通的字符串数据。

对象(属性和值)、Map(键值对)

  k: v: 在下一行来写对象得到属性和值的关系,注意缩进,对象还是 k: v 方式。

1friends: 
2	lastName: zyxwmj.top
3	age: 20

  单行写法:

1friends: {lastName: zhangsan,age: 18}

数组,List,Set

  用 -值 表示数组中的一个元素

1pets: 
2    - cat
3    - dog
4    - pig

  单行写法:

1pets: [cat,dog,pig]

总结

 1person:
 2  lastName: hello
 3  age: 18
 4  boss: false
 5  # 时间类型
 6  date: 2017/12/12
 7  array:
 8    - 3
 9    - 2
10  list:
11    - lisi
12    - zhaoliu
13  set:
14    - lisi
15    - zhaoliu
16  map: {k1: v1, k2: v2}
17  dog:
18    name: 小狗
19    age: 10

三、属性注入

  在实际开发中,我们为了方便管理项目中的常量或配置。常常将这些配置写入到配置文件中,在项目运行时,将配置注入到配置类中。

  为了方便我们编写配置文件,导入 SpringBoot 提供的配置文件处理,配置文件进行绑定后就会有提示。在 pom.xml 文件中导入以下依赖:

1        <dependency>
2            <groupId>org.springframework.boot</groupId>
3            <artifactId>spring-boot-configuration-processor</artifactId>
4        </dependency>

1、@ConfigurationProperties

  @ConfigurationProperties 注解可以将配置文件中的属性进行映射,注入到配置类中。

  例如,我们在配置文件中写入以下配置:

1dog:
2  name: 小狗
3  age: 10

  创建一个实体类,加上 @Component 注解,将当前类注入到 IOC 容器中。然后通过 @ConfigurationProperties 注解的 prefix 的属性值与配置文件的配置进行绑定。

注意: 类中成员变量的值必须与配置文件中的键对应,且类中必须有 Set 方法,否则无法注入进去。

 1/**
 2 * @Component 把当前类注入到容器中
 3 * @ConfigurationProperties 的 prefix值 和配置文件的对应,其他名字只有相同才能注入进去,必须有 set 方法
 4 */
 5@Component
 6@ConfigurationProperties(prefix = "dog")
 7public class Dog {
 8
 9    String name;
10
11    int age;
12
13    public void setName(String name) {
14        this.name = name;
15    }
16
17    public void setAge(int age) {
18        this.age = age;
19    }
20
21    @Override
22    public String toString() {
23        return "Dog{" +
24                "name='" + name + '\'' +
25                ", age=" + age +
26                '}';
27    }
28}

使用 @ConfigurationProperties 注入 person
  注入上面 YML 中配置的 person。

 1@Component
 2@ConfigurationProperties(prefix = "person")
 3public class Person {
 4
 5
 6    String lastName;
 7    int age;
 8    boolean boss;
 9    Date date;
10    int[] array;
11    List<String> list;
12    Set<String> set;
13    Map<String, String> map;
14    Dog dog;
15
16    @Override
17    public String toString() {
18        return "Person{" +
19                "lastName='" + lastName + '\'' +
20                ", age=" + age +
21                ", boss=" + boss +
22                ", date=" + date +
23                ", array=" + Arrays.toString(array) +
24                ", list=" + list +
25                ", set=" + set +
26                ", map=" + map +
27                ", dog=" + dog +
28                '}';
29    }
30
31    public void setLastName(String lastName) {
32        this.lastName = lastName;
33    }
34
35    public void setAge(int age) {
36        this.age = age;
37    }
38
39    public void setBoss(boolean boss) {
40        this.boss = boss;
41    }
42
43    public void setDate(Date date) {
44        this.date = date;
45    }
46
47    public void setArray(int[] array) {
48        this.array = array;
49    }
50
51    public void setList(List<String> list) {
52        this.list = list;
53    }
54
55    public void setSet(Set<String> set) {
56        this.set = set;
57    }
58
59    public void setMap(Map<String, String> map) {
60        this.map = map;
61    }
62
63    public void setDog(Dog dog) {
64        this.dog = dog;
65    }
66}

2、快速测试

  通过 SpringBoot 提供的单元测试,可以快速进行测试属性值是否注入到了类中。

 1@SpringBootTest
 2public class JournalApplicationTests {
 3
 4
 5    @Autowired
 6    Dog dog;
 7
 8    @Test
 9    public void demo() {
10        System.out.println(dog);
11    }
12}

3、@Value

  通过 @Value 注解可以为单个成员变量注入值,首先通过 @Component 注解,将当前类注入到 IOC 容器中。

 1@Component
 2public class Dog {
 3
 4    @Value("${dog.name}")
 5    String name;
 6    @Value("${dog.age}")
 7    int age;
 8
 9
10    public void setName(String name) {
11        this.name = name;
12    }
13
14    public void setAge(int age) {
15        this.age = age;
16    }
17
18    @Override
19    public String toString() {
20        return "Dog{" +
21                "name='" + name + '\'' +
22                ", age=" + age +
23                '}';
24    }
25}

4、@Validation

  使用 @Validation + @ConfigurationProperties 注解可以对注入的属性值进行限制(JSR303 数据效验),例如,使用 @Email 可以限制注入的属性格式必须为邮箱,否则会报错。

 1@Component
 2@Validated
 3@ConfigurationProperties(prefix = "dog")
 4public class Dog {
 5
 6    /**
 7     *  @Email 注解
 8     *  name 必须是邮箱格式,否则报错
 9     */
10    @Email
11    String name;
12    int age;
13
14
15    public void setName(String name) {
16        this.name = name;
17    }
18
19    public void setAge(int age) {
20        this.age = age;
21    }
22
23    @Override
24    public String toString() {
25        return "Dog{" +
26                "name='" + name + '\'' +
27                ", age=" + age +
28                '}';
29    }
30}

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:

1@Resource
2private Environment environment;

  获取配置文件中的指定值(其他用法不在展示):

1environment.getProperty("ras.key.window.privateFilePath");

四、配置文件占位符

1、随机数

占位符 作用
${random.value} 生成随机字符串
${random.uuid} 生成唯一序列
${random.int} 生成随机数字,最值为长度为int
${random.long} 生成随机数字,最值为长度为long
${random.int(10)} 生成随机数字,最值为长度为10

2、获取之前的配置

  通过占位符获取之前配置的值,如果没有可以使用 :默认值指定默认值,例如如下,name的值为 小狗10

1dog:
2  name: 小狗${dog.age:666}
3  age: 10

五、注入外部配置文件

  使用 @propertySource@ImportResource 注解来引用外部配置文件。

1、@propertySource

  @ConfigurationProperties@Value 注解默认是在 SpringBoot 的主配置文件中查找配置项,我们也可以使用外部配置文件,进行参数注入。使用 @propertySource 加载指定的配置文件(只能是 properties 文件)。首相创建一个名为 config.properties 的配置文件,内容如下:

1dog.name= 小狗
2dog.age= 18

  然后使用 @propertySource 注解,通过 value 属性值指定配置文件的位置即可。

 1@PropertySource(value = "classpath:config.properties")
 2@ConfigurationProperties(prefix = "dog")
 3@Component
 4public class Dog {
 5
 6    String name;
 7    int age;
 8
 9
10    public void setName(String name) {
11        this.name = name;
12    }
13
14    public void setAge(int age) {
15        this.age = age;
16    }
17
18    @Override
19    public String toString() {
20        return "Dog{" +
21                "name='" + name + '\'' +
22                ", age=" + age +
23                '}';
24    }
25}
properties 文件乱码

  如果将 properties 文件中的汉字注入到实体类中出现乱码的话,修改 idea 的配置即可。

1.png

2、@ImportResource

  SpringBoot 里面没有 Spring 的配置文件,我们自己编写的配置文件,也不能自动识别,想让 Spring 的配置文件生效,我们可以使用 @ImportResource 注解。

  首先我们使用传统 Spring 的方式将类注入到容器中。

1<?xml version="1.0" encoding="UTF-8"?>
2<beans xmlns="http://www.springframework.org/schema/beans"
3       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4       xsi:schemaLocation="http://www.springframework.org/schema/beans
5http://www.springframework.org/schema/beans/spring-beans.xsd">
6
7    <bean id="helloService" class="top.zyxwmj.journal.controller.HelloService"/>
8</beans>
测试

  我们通过 ApplicationContext 类的 containsBean 方法判断指定组件是否注入到了容器中。

 1@SpringBootTest
 2public class JournalApplicationTests {
 3
 4    @Autowired
 5    ApplicationContext ioc;
 6
 7    @Test
 8    void contextLoads() {
 9        // 判断ioc中是否有指定组件
10        System.out.println(ioc.containsBean("helloService"));
11    }
12
13}

  测试结果为 false ,因为我们的 Spring 的配置文件并没有和 SpringBoot 进行关联。我们在 SpringBoot 的启动类上加 @ImportResource 注解,指向 Spring 的配置文件即可。

1@ImportResource(locations = {"classpath:beans.xml"})
2@SpringBootApplication
3public class JournalApplication {
4
5    public static void main(String[] args) {
6        SpringApplication.run(JournalApplication.class, args);
7    }
8
9}

3、@Configuration 和 @Bean

  在实际开发中,我们不编写 Spring 的配置文件。SpringBoot 推荐使用容器中添加组件的方式,推荐使用全注解方式,例如:

 1/**
 2 * @Configuration 告诉 SpringBoot 这是一个配置类
 3 */
 4@Configuration
 5public class MyConfig {
 6
 7    /**
 8     * 将方法的返回值添加到容器中,容器中这个组件默认的id就是方法名
 9     */
10    @Bean
11    public HelloService helloService() {
12        return new HelloService();
13    }
14}
15

标题:SpringBoot 配置值的注入和YML的编写
作者:Yi-Xing
地址:http://zyxwmj.top/articles/2020/03/29/1585470511417.html
博客中若有不恰当的地方,请您一定要告诉我。前路崎岖,望我们可以互相帮助,并肩前行!