一、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 的配置即可。

1.png

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:10014/articles/2020/03/29/1585470511417.html
博客中若有不恰当的地方,请您一定要告诉我。前路崎岖,望我们可以互相帮助,并肩前行!