4.配置文件

四、配置文件

1、配置文件简介

4.1.1、配置文件的作用

Sping Boot的配置文件的作用有以下两点

  1. 对一些默认配置的配置值进行修改
  2. 自定义一些配置值供程序使用

4.1.2、配置文件格式

SpringBoot可以识别三种格式的配置文件

  1. roperties格式

    传统格式/默认格式

    【示例】在这里插入图片描述

  2. yml

    主流格式

    【示例】在这里插入图片描述

  3. yaml

    不太常用

    【示例】在这里插入图片描述

4.1.3、配置文件的分类

配置文件分为默认配置文件和自定义配置文件两种

4.1.3.1、默认配置文件
(1)、默认配置文件名

Spring Boot的默认配置文件名为

  • application.properties
  • application.yml
  • application.yaml

该配置文件在指定目录下可以被SpringBoot自动识别并加载

这三种格式的配置文件可以同时存在

在这里插入图片描述

(2)、文件格式加载顺序

默认配置文件是在SpringBoot项目启动的时候被自动加载的,其内部的相关设置会自动覆盖SpringBoot默认的对应设置项,所有的配置项均会保存到Spring容器之中

三种格式的配置文件同时存在时的加载顺序如下

  • application.properties(最高)
  • application.yml(次之)
  • application.yaml(最低)

不同配置文件中相同配置按照加载优先级相互覆盖,不同配置文件中不同配置全部保留

【测试】测试配置文件的加载顺序

在springboot-01-001模块中定义三个配置文件

  • application.properties

    server.port=8081
    
  • application.yml

    server:
      port: 8082
      application:
        name: name2
      size: 100
    
  • application.yaml

    server:
      application:
        name: name3
      port: 8083
    
  • 单测代码

    package com.longdidi;
    
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.test.context.SpringBootTest;
    
    @SpringBootTest
    class SpringbootTest01 {
    
        @Value("${server.port}")
        String port;
    
        @Value("${server.application.name}")
        String name;
    
        @Value("${server.size}")
        String size;
    
        @Test
        void contextLoads() {
        }
    
        @Test
        void test1() {
            System.out.println("启用的端口号:" + port);
            System.out.println("启用的名字:" + name);
            System.out.println("启用的大小:" + size);
        }
    }
    
  • 测试结果

    1.配置文件的优先级 1.1、端口号在三个文件中都有,加载的是application.properties文件中的,因此该文件的优先级最高; 1.2、名字属性在application.yml和application.yaml文件中都存在,加载的是application.yml中的 因此的值application.yml的优先级次之,application.yaml的优先级最低 2.配置文件加载 2.1、名字属性在在application.yml和application.yaml文件中都存在,因为application.yml的优先级 高,因此application.yml会覆盖application.yaml中的同名配置文件 2.2、大小属性在application.yaml文件中存在,因此会被保留下来

    在这里插入图片描述

(3)、默认配置文件位置

SpringBoot的全局默认配置文件想要被SpringBoot自动加载需要放置到指定的位置

我们配置的main/resources其实就是下面的classpath

  1. file:./config/*/

    根目录(项目文件夹)下的config/目录

  2. file:./config/

    根目录(项目文件夹)下的/config子目录中

  3. file:./

    根目录(项目文件夹)下

  4. classpath:/

    项目的resources目录中

  5. classpath:/config/

    项目的resources下的/config子目录中

在这四个位置的属性文件(application.properties或application.yml或application.yaml)会被SpringBoot自动识别并加载

可以在源码中看到关于配置文件位置的定义

在这里插入图片描述

(4)、配置文件优先级

不要在公共配置文件application.properties和自定义配置文件xxx.properties中配置相同的的配置项的不同值,因为公共配置文件的优先权最高,会覆盖掉自定义配置文件中的内容

可以这么理解:公共配置文件中的某个配置在启动时加载到Spring容器中,之后又在另外一个自定义配置文件中加载了同名的配置项,二者有不同的值,但是系统会检查二者的优先权,谁高谁留,谁低谁走,最后自定义配置文件中的值无效

优先级原则

其原则就是

  1. 根目录大于resources目录
  2. “/config/*/目录” > “/config目录” > “/目录”
  3. properties文件大于yml文件,yml文件大于yaml文件

注意这里的根目录一定是项目所在工程的根项目目录

  • 根项目

    如果项目本身就是一个独立的项目,那么根目录就是项目的目录

    如下项目的根路径就是项目目录

    在这里插入图片描述

  • 子项目

    如果项目本身为其它项目下的子项目,那么根路径是父项目的路径

    如下

    在这里插入图片描述

优先级顺序
  1. 第一优先级

    项目根目录下的/config/*/子目录中

    config/*/application.properties

    config/*/application.yml

    config/*/application.yaml

  2. 第二优先级

    项目根目录下的/config子目录中

    config/application.properties

    config/application.yml

    config/application.yaml

  3. 第三优先级

    项目根目录下

    application.properties

    application.yml

    application.yaml

  4. 第四优先级

    项目的resources下的/config子目录中

    resources/config/application.properties

    resources/config/application.yml

    resources/config/application.yaml

  5. 第五优先级

    项目的resources目录中

    resources/application.properties

    resources/application.yml

    resources/application.yaml

Spring Boot 会按照这个顺序来加载配置文件

如果在多个位置有相同的属性定义,那么最先检查的位置中的属性值将优先使用

示例图如下

在这里插入图片描述

优先级测试

创建springboot-04-002模块

  • file文件示例图

    在这里插入图片描述

  • classpath文件示例图

    在这里插入图片描述

  • 启动测试

    先加载的是./file/config/*/路径下的配置文件,其它顺序可以自行测试

    在这里插入图片描述

4.1.3.2、自定义配置文件

SpringBoot支持自定义配置文件,自定义配置文件不能被SpringBoot自动加载,需要手动去进行加载

使用步骤

  1. 创建自定义配置文件

  2. 创建配置类

    使用@ConfigurationProperties注解来绑定配置文件中的属性,同时使用@PropertySource注解来指定配置文件的位置

  3. 使用配置类

    在需要使用这些配置信息的地方通过Spring的依赖注入(@Autowired)来注入配置类实例,然后调用其getter方法来获取配置值

【测试】创建自定义模块springboot-04-003

  • 编写配置文件

    src/main/resources目录下新建自定义配置文件

    例如创建config.properties并在其中编写需要的配置信息

    com.example.name=test
    com.example.age=25
    
  • 创建配置类

    创建一个配置类,使用@ConfigurationProperties注解来绑定配置文件中的属性,同时使用@PropertySource注解来指定配置文件的位置

    package com.longdidi;
    
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.context.annotation.PropertySource;
    import org.springframework.stereotype.Component;
    
    @Component
    @ConfigurationProperties(prefix = "com.example") // 绑定配置文件中的属性
    @PropertySource("classpath:config.properties") // 指向定配置文件的位置
    public class TestProperties {
    
        private String name;
        private int age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    
  • 使用配置类

    在需要使用这些配置信息的地方通过Spring的依赖注入(@Autowired)来注入配置类实例,然后调用其getter方法来获取配置值

    package com.longdidi;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class TestController {
    
        @Autowired
        private TestProperties testProperties;
    
        @GetMapping("/test")
        public String test() {
            return "Name: " + testProperties.getName() + ", Age: " + testProperties.getAge();
        }
    }
    
  • 测试

    启动项目访问http://localhost:8080/test

    在这里插入图片描述

4.1.4、YML配置文件自动提示

在SpringBoot项目中,默认只有在".properties"配置文件中才能自动提示配置信息,yml和yaml配置文件都不会自动提示,并且YML文件和其它位置的properties文件也不是配置文件的图标

如下

在这里插入图片描述

这是因为SpringBoot默认不会自动加载这些配置文件,如果想要在YML配置文件中也有自动提示功能,则需要做如下配置

(1)、配置Spring
  • File ->ProjectStructure

    在这里插入图片描述

  • Facets添加Spring配置

    在这里插入图片描述

  • 选择项目

    在这里插入图片描述

(2)、修改配置
  • File ->ProjectStructure

    在这里插入图片描述

  • 选中对应项目/工程

    在这里插入图片描述

  • 点击OK后可查看已选择的文件

    在这里插入图片描述

  • 修改后查看文件图标

    在这里插入图片描述

(3)、测试

在yml配置文件中输入port测试,看到已经可以做自动提示

在这里插入图片描述

2、YML配置文件

4.2.1、YML配置文件概述

SpringBoot采用集中式配置管理,所有的配置都编写到一个配置文件中:application.properties

如果配置非常多,层级不够分明,因此SpringBoot为了提高配置文件可读性,也支持YAML格式的配置文件:application.yml

YAML是一种人类可读的数据序列化格式,它通常用于配置文件,在各种编程语言中作为一种存储或传输数据的方式

YAML的设计目标是易于阅读和编写,同时保持足够的表达能力来表示复杂的数据结构

YAML文件的扩展名可以是.yaml或者.yaml

4.2.2、常见的数据交换格式

常见的数据存储和交换的格式有四种,它们各有特点和适用场景

Properties

  • 这种格式主要用于Java应用程序中的配置文件。它是键值对的形式,每一行是一个键值对,使用等号或冒号分隔键和值。
  • 特点是简单易懂,但在处理复杂结构的数据时显得力不从心。

XML (eXtensible Markup Language)

  • XML是一种标记语言,用来描述数据的格式。它支持复杂的数据结构,包括嵌套和属性。
  • XML文档具有良好的结构化特性,适合传输和存储结构化的数据。但是,XML文档通常体积较大,解析起来也比较耗资源。

JSON (JavaScript Object Notation)

  • JSON是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。它基于JavaScript的一个子集,支持多种数据类型,如数字、字符串、布尔值、数组和对象。
  • JSON因为简洁和高效而广泛应用于Web应用程序之间进行数据交换。

YAML (YAML Ain’t Markup Language)

  • YAML设计的目标之一就是让人类更容易阅读。它支持类似JSON的数据序列化,但提供了更多的灵活性,例如缩进来表示数据结构。
  • YAML非常适合用来编写配置文件,因为它允许以一种自然的方式组织数据,并且可以包含注释和其他人类可读的元素。

总结来说这四种格式都可以用来存储和交换数据,但它们的设计初衷和最佳使用场景有所不同。选择哪种格式取决于具体的应用需求、数据复杂度、性能要求等因素。

4.2.3、语法规则

  • 大小写敏感

  • YAML用换行+空格来表示层级关系,每行结尾使用冒号结束

    缩进时不允许使用Tab键,只允许使用空格

    缩进的空格数目不重要(大部分建议2个或4个空格),只要相同层级的元素左侧对齐即可

    例如

    1. properties文件中这样的配置

      myapp.name=mall
      
    2. yaml文件中就需要这样配置

      myapp:
        name: mall
      
  • 同层级左侧对齐

    例如

    1. properties文件中有这样的配置

      myapp.name=mall
      myapp.count=10
      
    2. yaml文件中就应该这样配置

      myapp:
        name: mall
        count: 10
      
  • 属性名与属性值之间使用冒号+空格作为分隔

    YAML使用一个空格来分隔属性名属性值

    例如

    1. properties文件中这样的配置:name=jack

    2. yaml文件中需要这样配置

      myapp:
        name: mall
      
  • # 表示注释(从这个字符一直到行尾,都会被解析器忽略)

  • 键必须是唯一的:在一个映射中键必须是唯一的

  • 数据结构:YAML支持多种数据类型

    包括以下几种类型

    1. 字符串:字符串可以不用引号标注
    2. 数字
    3. 布尔值
    4. 数组、list集合
    5. map键值对

核心规则: 数据前面要加空格与冒号隔开

4.2.4、YML中的转义

普通文本也可以使用单引号或双引号括起来(当然普通文本也可以不使用单引号和双引号括起来)

  • 单引号括起来

    单引号内所有的内容都被当做普通文本,不转义(例如字符串中有\n,则\n被当做普通的字符串)

  • 双引号括起来

    双引号中有 \n 则会被转义为换行符

【示例】在测试模块springboot-04-004中测试

application.yml

# 测试单引号与双引号的转义区别
spring:
  name1: 'hello\tworld1\n'
  name2: "hello\tworld2\n"

Test01.java

package com.longdidi;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class Test01 {

    @Value("${spring.name1}")
    String name1;

    @Value("${spring.name2}")
    String name2;

    @Test
    public void test01() {
        System.out.println("name1:" + name1);
        System.out.println("name2:" + name2);
    }

}

测试结果

在这里插入图片描述

4.2.5、保留文本格式

"|"符号可以保留文本的格式,将文本写到这个符号的下层会自动保留格式

【示例】在模块springboot-04-004中测试

application.properties

# 测试|保留格式功能
test1:
  app1: |
    123
    234
    345

Test02.java单测代码

package com.longdidi;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class Test02 {

    @Value("${test1.app1}")
    String app1;

    @Test
    public void test01() {
        System.out.println("app1:" + app1);
    }

}

测试结果

在这里插入图片描述

4.2.6、文档切割

YAML 文件可以由一个或多个文档组成(也即相对独立的组织结构组成)

文档间使用"—" (三个横线)在每文档开始作为分隔符(如果只是单个文档则分隔符"—"可省略)

每个文档并不需要使用结束符"…"来表示结束,但是对于网络传输或者流来说,作为明确结束的符号有利于软件处理

在这里插入图片描述

4.2.7、数据表示形式

在模块springboot-04-005模块中测试

(1)、字面量(键值对)

纯量是最基本的、不可再分的值

包括

  • 整数
  • 浮点数
  • 无穷数字
  • 无效数字
  • 空值
  • Null
  • 布尔值
  • 时间
  • 日期

使用":"(冒号) + 空格表示单个键值对

  1. 数值

    数值直接以字面量的形式表示

    #测试纯量的值
    integer: 12345         # 读取yamL数据中的十进制数
    second: 00000001       #读取yamL数据中的二进制数
    octal: 012        # 读取yamL数据中的八进制数
    hex: 0xFF          # 读取yamL数据中的十六进制数
    float: 1.23e+3     # 读取yamL数据中的浮点数,支持科学计数法
    fixed: 13.67       # 读取yamL数据中的Double类型数据
    
  2. 布尔值

    布尔值用true和false表示

    isSet: true # 读取yamL数据中的布尔类型
    
  3. 无穷大数字

    minmin: -.inf      # 读取yamL数据中的负无穷大数据
    
  4. 无效数字

    notNumber: .NaN    # 读取yamL数据中的无效数字
    
  5. 读取空值

    testempty:  # 读取yamL数据中的空值
    
  6. 读取null值

    null用"~"表示

    testnull: ~ #读取yamL数据中的null值
    
  7. 时间

    时间和日期之间使用T连接,最后使用+代表时区

    #测试时间
    time1: 2026-02-17T15:02:31+08:00
    
  8. 日期

    日期必须使用yyyy-MM-dd格

    #测试日期
    date1: 1976-07-31
    

【示例】在模块springboot-04-005中测试

  • application.yml

    #测试纯量的值
    integer: 12345         # 读取yamL数据中的十进制数
    second: 00000001       #读取yamL数据中的二进制数
    octal: 012        # 读取yamL数据中的八进制数
    hex: 0xFF          # 读取yamL数据中的十六进制数
    float: 1.23e+3     # 读取yamL数据中的浮点数,支持科学计数法
    fixed: 13.67       # 读取yamL数据中的Double类型数据
    minmin: -.inf      # 读取yamL数据中的负无穷大数据
    notNumber: .NaN    # 读取yamL数据中的无效数字
    testempty:  # 读取yamL数据中的空值
    testnull: ~ #读取yamL数据中的null值
    isSet: true # 读取yamL数据中的布尔类型
    testdate: 2025-08-23   # 读取yamL数据中的日期类型
    datetime: 2025-08-23T02:02:00.1z  # 读取yamL数据中的时间类型
    
  • SpringbootTest01.java

    package com.longdidi;
    
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.test.context.SpringBootTest;
    
    /**
     * 测试读取单一变量的值
     */
    @SpringBootTest
    class SpringbootTest01 {
        //读取yamL数据中的十进制数
        @Value("${integer}")
        private Integer integer;
    
        //读取yamL数据中的二进制数
        @Value("${second}")
        private Integer second;
    
        //读取yamL数据中的八进制数
        @Value("${octal}")
        private Integer octal;
    
        //读取yamL数据中的十六进制数
        @Value("${hex}")
        private Integer hex;
    
        //读取yamL数据中的浮点数
        @Value("${float}")
        private Float floatnum;
    
        //读取yamL数据中的Double类型数据
        @Value("${fixed}")
        private Double fixed;
    
        //读取yamL数据中的负无穷大数据
        @Value("${minmin}")
        private Double minmin;
    
        //读取yamL数据中的无效数字
        @Value("${notNumber}")
        private String notNumber;
    
        //读取yamL数据中的空值
        @Value("${testempty}")
        private String testempty;
    
        //读取yamL数据中的null值
        @Value("${testnull}")
        private String testnull;
    
        //读取yamL数据中的布尔类型
        @Value("${isSet}")
        private Boolean isSet;
    
        //读取yamL数据中的日期类型
        @Value("${testdate}")
        private String testdate;
    
    
        //读取yamL数据中的时间类型
        @Value("${datetime}")
        private String datetime;
    
        @Test
        void testValue() {
            System.out.println("读取yamL数据中的十进制数=======:" + integer);
            System.out.println("读取yamL数据中的二进制数=======:" + second);
            System.out.println("读取yamL数据中的八进制数=======:" + octal);
            System.out.println("读取yamL数据中的十六进制数=======:" + hex);
            System.out.println("读取yamL数据中的浮点数=======:" + floatnum);
            System.out.println("读取yamL数据中的Double类型数据=======:" + fixed);
            System.out.println("读取yamL数据中的负无穷大数据=======:" + minmin);
            System.out.println("读取yamL数据中的无效数字=======:" + notNumber);
            System.out.println("读取yamL数据中的空值=======:" + testempty);
            System.out.println("读取yamL数据中的null值=======:" + testnull);
            System.out.println("读取yamL数据中的布尔类型=======:" + isSet);
            System.out.println("读取yamL数据中的日期类型=======:" + testdate);
            System.out.println("读取yamL数据中的时间类型=======:" + datetime);
        }
    
    }
    
  • 测试结果

    在这里插入图片描述

(2)、字符串

字符串可以用引号表示,也可以不使用,可以使用双引号包裹特殊字符

  1. 字符串默认不使用引号表示

    # 字符串默认不使用引号表示
    str1: hello world
    
  2. 字符串之中包含空格或特殊字符需要放在引号之中

    #字符串之中包含空格或特殊字符需要放在引号之中
    str2: 'hello: world'
    
  3. 单引号不会对特殊字符转义,双引号会对特殊字符转义

    #单引号不会对特殊字符转义,双引号会对特殊字符转义
    str3: 'hello\tworld1\n'
    str4: "hello\tworld2\n"
    
  4. 单引号之中如果还有单引号则必须连续使用两个单引号转义

    #单引号之中如果还有单引号则必须连续使用两个单引号转义
    str5: 'labor''s day'
    
  5. 字符串可以写成多行,从第二行开始,必须有一个单空格缩进,换行符会被转为空格

    # 字符串可以写成多行,从第二行开始,必须有一个单空格缩进,换行符会被转为空格
    str6: this
      is
      a
      cat
    # 输出结果str6:this is a cat
    
  6. 使用 “|” 和文本内容

    使用 “|” 表示的块保留块中已有的回车换行

    # 使用 "|" 和文本内容缩进表示的块:保留块中已有的回车换行
    str7: |
      Foo
      Bar
      {this: 'Foo\nBar\n'}
    
  7. 使用 “>” 和文本内容

    使用 “>” 将块中回车替换为空格,最终连接成一行

    # 使用 ">" 和文本内容缩进表示的块:将块中回车替换为空格,最终连接成一行
    str8: >
      Foo
      Bar
    
  8. +表示保留文字块末尾的换行,-表示删除字符串末尾的换行

    # +表示保留文字块末尾的换行,-表示删除字符串末尾的换行
    str9: |+
      Foo
    
    str10: |-
      Foo
    
  9. 字符串之中可以插入 HTML 标记

    #  字符串之中可以插入 HTML 标记
    str11: |
      <p style="color: red">
        dog
      </p>
    

【测试】在模块springboot-04-005中测试

  • application.yml

    ##################测试字符串
    # 1、字符串默认不使用引号表示
    str1: hello world
    
    # 2、字符串之中包含空格或特殊字符需要放在引号之中
    str2: 'hello: world'
    
    # 3、单引号不会对特殊字符转义,双引号会对特殊字符转义
    str3: 'hello\tworld1\n'
    str4: "hello\tworld2\n"
    
    # 4、单引号之中如果还有单引号则必须连续使用两个单引号转义
    str5: 'labor''s day'
    
    # 5、字符串可以写成多行,从第二行开始,必须有一个单空格缩进,换行符会被转为空格
    str6: this
      is
      a
      cat
    
    # 6、使用 "|" 和文本内容缩进表示的块:保留块中已有的回车换行
    str7: |
      Foo
      Bar
      {this: 'Foo\nBar\n'}
    
    # 7、使用 ">" 和文本内容缩进表示的块:将块中回车替换为空格,最终连接成一行
    str8: >
      Foo
      Bar
    
    # 8、+表示保留文字块末尾的换行,-表示删除字符串末尾的换行
    str9: |+
      Foo
    
    str10: |-
      Foo
    
    #  9、字符串之中可以插入 HTML 标记
    str11: |
      <p style="color: red">
        dog
      </p>
    
  • SpringbootTest02.java

    package com.longdidi;
    
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.test.context.SpringBootTest;
    
    @SpringBootTest
    class SpringbootTest02 {
    
        @Value("${str1}")
        String str1;
        @Value("${str2}")
        String str2;
        @Value("${str3}")
        String str3;
        @Value("${str4}")
        String str4;
        @Value("${str5}")
        String str5;
        @Value("${str6}")
        String str6;
        @Value("${str7}")
        String str7;
        @Value("${str8}")
        String str8;
        @Value("${str9}")
        String str9;
        @Value("${str10}")
        String str10;
        @Value("${str11}")
        String str11;
    
        @Test
        public void test01() {
            System.out.println("1===>字符串默认不使用引号表示str1:" + str1);
            System.out.println("2===>字符串之中包含空格或特殊字符需要放在引号之中str2:" + str2);
            System.out.println("3===>单引号不会对特殊字符转义str3:" + str3);
            System.out.println("3===>双引号会对特殊字符转义str4:" + str4);
            System.out.println("4===>单引号之中如果还有单引号则必须连续使用两个单引号转义str5:" + str5);
            System.out.println("5===>字符串可以写成多行,从第二行开始,必须有一个单空格缩进,换行符会被转为空格str6:" + str6);
            System.out.println("6===>使用 \"|\" 和文本内容缩进表示的块保留块中已有的回车换行str7:" + str7);
            System.out.println("7===>使用 \">\" 将块中回车替换为空格,最终连接成一行str8:" + str8);
            System.out.println("8===>+表示保留文字块末尾的换行str9:" + str9);
            System.out.println("8===>-表示删除字符串末尾的换行str10:" + str10);
            System.out.println("9===>字符串之中可以插入 HTML 标记str11:" + str11);
        }
    }
    
  • 测试结果

    在这里插入图片描述

(3)、数组

在属性名书写位置的下方使用减号作为数据开始符号,每行书写一个数据,减号与数据间空格分隔

  • 单个数组项

    使用"-"(横线) + 单个空格表示单个列表项

    #数组
    likes:
      - game
      - music
      - sleep
    
  • 一组数据

    使用"[]“表示一组数据,数据之间使用”,"逗号分隔

    #数组
    address: [北京,上海,重庆]
    
(4)、对象
  • 语法格式

    #对象
    key1:
      key2:
        key...N: value值
    
  • 使用示例

    #对象
    user:
      name: 赵丽颖
      age: 18
      address: 北京
    
(5)、对象+数组
  • 格式1

    users:
      - name: zhangsan
        age: 9
      - name: lisi
        age: 20
    
  • 格式2

    users1:
      -
        name: zhangsan
        age: 9
      -
        name: lisi
        age: 20
    
  • 格式3

    #这种格式中大括号内的键值之间不需要空格
    users3: [{name:zhangsan,age:18},{name:lisi,age:17}]
    
(6)、锚点引用
  • 使用 “&” 定义数据锚点(即要复制的数据)
  • << 表示合并到当前数据
  • 使用 “*” 引用上述锚点数据(即数据的复制目的地)
#############锚点使用
defaults: &defaults
  adapter: postgres
  host: localhost
development:
  database: myapp_development
  <<: *defaults
test:
  database: myapp_test
  <<: *defaults

#相当于
defaults1:
  adapter: postgres
  host: localhost
development1:
  database: myapp_development
  adapter: postgres
  host: localhost
test1:
  database: myapp_test
  adapter: postgres
  host: localhost
(7)、Map

使用"{}"表示一个键值表

语法

  • key: {key1: value1, key2: value2, …}

示例

#键值表
items: {number: 1234, descript: cpu, price: ¥800.00}
(8)、组合表示

每个结构都可以嵌套组成复杂的表示结构

#组合,相当于{Color: [blue, red, green]}
Color:
  - blue
  - red
  - green

div:
  - border: {color: red, width: 2px}
  - background: {color: green}
  - padding: [0, 10px, 0, 10px]
    
# 使用缩进表示的键值表与列表项
# 相当于下面的JSON表示
# item: [{item:cpu, model:i3, price:¥800.00}, {item:HD, model:WD, price: ¥450.00}]
item:
  - item: cpu
    model: i3
    price: ¥800.00
  - item: HD
    model: WD
    price: ¥450.00

4.2.8、引用属性值

在配置文件中可以使用**${属性名}**方式引用属性值

在这里插入图片描述

如果属性中出现特殊字符,可以使用双引号包裹起来作为字符解析

在这里插入图片描述

3、绑定属性值

4.3.1、@Value()注解读取

@Value注解可以将application.properties/application.yml文件中的配置信息注入/绑定到java对象的属性上

(1)、读取单一值
  • 使用@Value配合SpEL读取单个数据
  • 如果数据存在多层级,依次书写层级名称即可

【测试】在模块springboot-04-006中测试

  • application.yml

    #测试纯量的值
    integer: 12345         # 读取yamL数据中的十进制数
    second: 00000001       #读取yamL数据中的二进制数
    octal: 012        # 读取yamL数据中的八进制数
    hex: 0xFF          # 读取yamL数据中的十六进制数
    float: 1.23e+3     # 读取yamL数据中的浮点数,支持科学计数法
    fixed: 13.67       # 读取yamL数据中的Double类型数据
    minmin: -.inf      # 读取yamL数据中的负无穷大数据
    notNumber: .NaN    # 读取yamL数据中的无效数字
    testempty:  # 读取yamL数据中的空值
    testnull: ~ #读取yamL数据中的null值
    isSet: true # 读取yamL数据中的布尔类型
    testdate: 2025-08-23   # 读取yamL数据中的日期类型
    datetime: 2025-08-23T02:02:00.1z  # 读取yamL数据中的时间类型
    
  • ConfigTests01.java

    package com.longdidi;
    
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.test.context.SpringBootTest;
    
    /**
     * 测试读取单一变量的值
     */
    @SpringBootTest
    class ConfigTests01 {
        //读取yamL数据中的十进制数
        @Value("${integer}")
        private Integer integer;
    
        //读取yamL数据中的二进制数
        @Value("${second}")
        private Integer second;
    
        //读取yamL数据中的八进制数
        @Value("${octal}")
        private Integer octal;
    
        //读取yamL数据中的十六进制数
        @Value("${hex}")
        private Integer hex;
    
        //读取yamL数据中的浮点数
        @Value("${float}")
        private Float floatnum;
    
        //读取yamL数据中的Double类型数据
        @Value("${fixed}")
        private Double fixed;
    
        //读取yamL数据中的负无穷大数据
        @Value("${minmin}")
        private Double minmin;
    
        //读取yamL数据中的无效数字
        @Value("${notNumber}")
        private String notNumber;
    
        //读取yamL数据中的空值
        @Value("${testempty}")
        private String testempty;
    
        //读取yamL数据中的null值
        @Value("${testnull}")
        private String testnull;
    
        //读取yamL数据中的布尔类型
        @Value("${isSet}")
        private Boolean isSet;
    
        //读取yamL数据中的日期类型
        @Value("${testdate}")
        private String testdate;
    
    
        //读取yamL数据中的时间类型
        @Value("${datetime}")
        private String datetime;
    
        @Test
        void testValue() {
            System.out.println("读取yamL数据中的十进制数=======:" + integer);
            System.out.println("读取yamL数据中的二进制数=======:" + second);
            System.out.println("读取yamL数据中的八进制数=======:" + octal);
            System.out.println("读取yamL数据中的十六进制数=======:" + hex);
            System.out.println("读取yamL数据中的浮点数=======:" + floatnum);
            System.out.println("读取yamL数据中的Double类型数据=======:" + fixed);
            System.out.println("读取yamL数据中的负无穷大数据=======:" + minmin);
            System.out.println("读取yamL数据中的无效数字=======:" + notNumber);
            System.out.println("读取yamL数据中的空值=======:" + testempty);
            System.out.println("读取yamL数据中的null值=======:" + testnull);
            System.out.println("读取yamL数据中的布尔类型=======:" + isSet);
            System.out.println("读取yamL数据中的日期类型=======:" + testdate);
            System.out.println("读取yamL数据中的时间类型=======:" + datetime);
        }
    
    }
    
  • 测试结果

    在这里插入图片描述

(2)、读取数组的值

语法格式: @Value(“${对象名.属性名1.属性名2…属性名[数组下标]}”)

语法:

  • 数组值使用“[下标]”获取
  • 属性值使用“.”获取

【测试】在模块springboot-04-006中测试

  • application.yml

    #数组
    likes:
      - game
      - music
      - sleep
    
    #数组
    address: [ 北京,上海,重庆 ]
    
  • ConfigTest02.java

    package com.longdidi;
    
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.test.context.SpringBootTest;
    
    /**
     * 测试读取数组的值
     */
    @SpringBootTest
    class ConfigTests02 {
        //读取yamL数据中的数组数据
        @Value("${likes[0]}")
        private String like;
    
        //读取yamL数据中的数组数据
        @Value("${address[1]}")
        private String address;
    
        @Test
        void testValue() {
            System.out.println("like=======:" + like);
            System.out.println("address=======:" + address);
        }
    
    }
    
  • 测试结果

    在这里插入图片描述

(3)、读取对象的值

语法: @Value(“${一级属性名.二级属性名…}”)

  • 属性值使用“.”获取

【示例】在模块springboot-04-006中测试

  • application.yml

    #对象
    user:
      age: 18
      address:
        province: 北京市
    
  • ConfigTest03.java

    package com.longdidi;
    
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.test.context.SpringBootTest;
    
    /**
     * 测试读取对象的值
     */
    @SpringBootTest
    class ConfigTests03 {
    
        //读取yamL数据中的对象1层数据
        @Value("${user.age}")
        private String age;
    
        //读取yamL数据中的对象2层数据
        @Value("${user.address.province}")
        private String province;
    
        @Test
        void testValue() {
            System.out.println("age=======:" + age);
            System.out.println("province=======:" + province);
        }
    
    }
    
  • 测试

    在这里插入图片描述

(4)、读取对象+数组

语法

  • 数组值使用“[下标]”获取
  • 属性值使用“.”获取

【示例】在模块springboot-04-006中测试

  • application.yml

    #对象+数组
    user1:
      - age: 18
        address: 北京市
      - age: 20
        address: 上海市
    #数组
    color:
      - [ blue, red, green ]     # 列表项本身也是一个列表
      - [ Age, Bag ]
    
    testborder:
      - border: [红色,绿色,蓝色]
      - padding: { number: 1234, descript: cpu, price: ¥800.00 }
    
  • ConfigTests04.java

    package com.longdidi;
    
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.test.context.SpringBootTest;
    
    /**
     * 测试读取数组对象的值
     */
    @SpringBootTest
    class ConfigTests04 {
    
        //读取yamL数据中的数组对象数据
        @Value("${user1[0].address}")
        private String address1;
    
        //读取yamL数据中的数组对象数据
        @Value("${color[0][1]}")
        private String color0;
    
        //读取yamL数据中的数组对象数据
        @Value("${testborder[0].border[2]}")
        private Object border;
    
        //读取yamL数据中的数组对象数据
        @Value("${testborder[1].padding.number}")
        private Object padding;
    
    
        @Test
        void testValue() {
            System.out.println("address1=======:" + address1);
            System.out.println("color0=======:" + color0);
            System.out.println("border=======:" + border);
            System.out.println("padding=======:" + padding);
        }
    
    }
    
  • 测试

    在这里插入图片描述

(5)、读取字符串的值
  • 单引号中的特殊字符不会转义
  • 双引号中的特殊字符会转义

【测试】在模块springboot-04-006中测试

  • application.yml

    ##################################测试字符串
    ##################测试字符串
    # 1、字符串默认不使用引号表示
    str1: hello world
    
    # 2、字符串之中包含空格或特殊字符需要放在引号之中
    str2: 'hello: world'
    
    # 3、单引号不会对特殊字符转义,双引号会对特殊字符转义
    str3: 'hello\tworld1\n'
    str4: "hello\tworld2\n"
    
    # 4、单引号之中如果还有单引号则必须连续使用两个单引号转义
    str5: 'labor''s day'
    
    # 5、字符串可以写成多行,从第二行开始,必须有一个单空格缩进,换行符会被转为空格
    str6: this
      is
      a
      cat
    
    # 6、使用 "|" 和文本内容缩进表示的块:保留块中已有的回车换行
    str7: |
      Foo
      Bar
      {this: 'Foo\nBar\n'}
    
    # 7、使用 ">" 和文本内容缩进表示的块:将块中回车替换为空格,最终连接成一行
    str8: >
      Foo
      Bar
    
    # 8、+表示保留文字块末尾的换行,-表示删除字符串末尾的换行
    str9: |+
      Foo
    
    str10: |-
      Foo
    
    #  9、字符串之中可以插入 HTML 标记
    str11: |
      <p style="color: red">
        dog
      </p>
    
  • ConfigTests05.java

    package com.longdidi;
    
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.test.context.SpringBootTest;
    
    @SpringBootTest
    public class ConfigTests05 {
        @Value("${str1}")
        String str1;
        @Value("${str2}")
        String str2;
        @Value("${str3}")
        String str3;
        @Value("${str4}")
        String str4;
        @Value("${str5}")
        String str5;
        @Value("${str6}")
        String str6;
        @Value("${str7}")
        String str7;
        @Value("${str8}")
        String str8;
        @Value("${str9}")
        String str9;
        @Value("${str10}")
        String str10;
        @Value("${str11}")
        String str11;
    
        @Test
        public void test01() {
            System.out.println("1===>字符串默认不使用引号表示str1:" + str1);
            System.out.println("2===>字符串之中包含空格或特殊字符需要放在引号之中str2:" + str2);
            System.out.println("3===>单引号不会对特殊字符转义str3:" + str3);
            System.out.println("3===>双引号会对特殊字符转义str4:" + str4);
            System.out.println("4===>单引号之中如果还有单引号则必须连续使用两个单引号转义str5:" + str5);
            System.out.println("5===>字符串可以写成多行,从第二行开始,必须有一个单空格缩进,换行符会被转为空格str6:" + str6);
            System.out.println("6===>使用 \"|\" 和文本内容缩进表示的块保留块中已有的回车换行str7:" + str7);
            System.out.println("7===>使用 \">\" 将块中回车替换为空格,最终连接成一行str8:" + str8);
            System.out.println("8===>+表示保留文字块末尾的换行str9:" + str9);
            System.out.println("8===>-表示删除字符串末尾的换行str10:" + str10);
            System.out.println("9===>字符串之中可以插入 HTML 标记str11:" + str11);
        }
    }
    
  • 测试

    在这里插入图片描述

(6)、读取键值表的值

语法: @Value(“${一级属性名.二级属性名…}”)

  • 属性值使用“.”获取

【测试】在模块springboot-04-006中测试

  • application.yml

    #键值表
    items: { number: 1234, descript: cpu, price: ¥800.00 }
    
  • ConfigTests06.java

    package com.longdidi;
    
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.test.context.SpringBootTest;
    
    /**
     * 测试读取键值表的值
     */
    @SpringBootTest
    public class ConfigTests06 {
        //读取yamL数据中键值表数据
        @Value("${items.number}")
        private String number;
    
        @Test
        void testValue() {
            System.out.println("number=======:" + number);
        }
    
    }
    
  • 测试

    在这里插入图片描述

(7)、读取锚点引用的值

语法: @Value(“${一级属性名.二级属性名…}”)

  • 属性值使用“.”获取

【测试】在模块springboot-04-006中测试

  • application.yml

    ###########################引用
    #############锚点使用
    defaults: &defaults
      adapter: postgres
      host: localhost
    development:
      database: myapp_development
      <<: *defaults
    test:
      database: myapp_test
      <<: *defaults
    
    #相当于
    defaults1:
      adapter: postgres
      host: localhost
    development1:
      database: myapp_development
      adapter: postgres
      host: localhost
    test1:
      database: myapp_test
      adapter: postgres
      host: localhost
    
  • ConfigTests07.java

    package com.longdidi;
    
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.test.context.SpringBootTest;
    
    /**
     * 测试读取锚点值
     */
    @SpringBootTest
    public class ConfigTests07 {
        //读取yamL数据中锚点数据数据
        @Value("${defaults.adapter}")
        private String adapter1;
    
        @Value("${defaults.host}")
        private String host1;
    
        @Value("${development.adapter}")
        private String adapter2;
    
        @Value("${development.host}")
        private String host2;
    
        @Value("${development.database}")
        private String database2;
    
        @Value("${test.adapter}")
        private String adapter3;
    
        @Value("${test.host}")
        private String host3;
    
        @Value("${test.database}")
        private String database3;
    
    
    
        @Test
        void testValue() {
            System.out.println("adapter1=======:" + adapter1);
            System.out.println("host1=======:" + host1);
            System.out.println("adapter2=======:" + adapter2);
            System.out.println("host2=======:" + host2);
            System.out.println("database2=======:" + database2);
            System.out.println("adapter3=======:" + adapter3);
            System.out.println("host3=======:" + host3);
            System.out.println("database3=======:" + database3);
        }
    
    }
    
  • 测试

    在这里插入图片描述

4.3.2、Environment读取

SpringBoot框架在启动的时候会将系统配置、环境信息全部封装到Environment对象中。如果要获取这些环境信息可以调用Environment接口的方法

在Spring Boot中,Environment接口提供了访问应用程序环境信息的方法,比如活动配置文件、系统环境变量、命令行参数等。Environment接口由Spring框架提供,Spring Boot应用程序通常会使用Spring提供的实现类AbstractEnvironment及其子类来实现具体的环境功能。

Environment对象封装的主要数据包括:

  1. Active Profiles: 当前激活的配置文件列表。Spring Boot允许应用程序定义不同的环境配置文件(如开发环境、测试环境和生产环境),通过激活不同的配置文件来改变应用程序的行为。
  2. System Properties: 系统属性,通常是操作系统级别的属性,比如操作系统名称、Java版本等。
  3. System Environment Variables: 系统环境变量,这些变量通常是由操作系统提供的,可以在启动应用程序时设置特定的值。
  4. Command Line Arguments: 应用程序启动时传递给主方法的命令行参数。
  5. Property Sources: Environment还包含了一个PropertySource列表,这个列表包含了从不同来源加载的所有属性。PropertySource可以来自多种地方,比如配置文件、系统属性、环境变量等。

【测试】在模块springboot-04-007中测试

  • application.yml

    #测试纯量的值
    integer: 12345     # 整数标准形式
    
    #对象
    user:
      age: 18
      address:
        province: 北京市
    
    #数组
    likes:
      - music
      - sleep
    
    #数组
    address: [ 北京,重庆 ]
    
    
    #对象+数组
    user1:
      - age: 18
        address: 北京市
      - age: 20
        address: 上海市
    #数组
    color:
      - [ blue, red, green ]     # 列表项本身也是一个列表
      - [ Age, Bag ]
    
    testborder:
      - border: [ 红色,绿色, ]
      - padding: { number: 1234, descript: cpu, price: ¥800.00 }
    
    
    
    #键值表
    items: { number: 1234, descript: cpu, price: ¥800.00 }
    
    #测试引号
    baseDir: c:\windows
    
    tempDir1: ${baseDir}\temp
    tempDir2: '${baseDir}\temp \t1 \t2 \t3'
    tempDir3: "${baseDir}\temp \t1 \t2 \t3"
    
  • ConfigTests01.java

    package com.longdidi;
    
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.core.env.Environment;
    
    /**
     * 测试使用Environment获取变量的值
     */
    @SpringBootTest
    class ConfigTests01 {
    
        @Autowired
        private Environment env;
    
    
        @Test
        void testValue() {
            System.out.println("integer=======:" + env.getProperty("integer"));
            System.out.println("user.age=======:" + env.getProperty("user.age"));
            System.out.println("user.address.province=======:" + env.getProperty("user.address.province"));
            System.out.println("likes[0]=======:" + env.getProperty("likes[0]"));
            System.out.println("address[1]=======:" + env.getProperty("address[1]"));
            System.out.println("user1[0].address=======:" + env.getProperty("user1[0].address"));
            System.out.println("color[0][1]=======:" + env.getProperty("color[0][1]"));
            System.out.println("testborder[0].border[2]=======:" + env.getProperty("testborder[0].border[2]"));
            System.out.println("testborder[1].padding.number=======:" + env.getProperty("testborder[1].padding.number"));
            System.out.println("items.number=======:" + env.getProperty("items.number"));
            System.out.println("tempDir1=======:" + env.getProperty("tempDir1"));
            System.out.println("tempDir2=======:" + env.getProperty("tempDir2"));
            System.out.println("tempDir3=======:" + env.getProperty("tempDir3"));
        }
    
    }![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/ab8416e0df744a9284959e09fd8e4190.png)
    
    
  • 测试结果

4.3.3、@PropertySource()注解读取

SpringBoot支持自定义配置文件,自定义配置文件不能被SpringBoot自动加载,需要手动去进行加载

无论对于哪里的配置文件,当需要使用其中配置内容的时候,就在当前类的顶部加注@PropertySource(“classpath:xxx.properties”)注解加载指定的配置文件

步骤

  1. 声明为配置类

    配置类上使用@Configuration标注以便纳入IOC容器管理

  2. 指定数据来源

    用这个注解来指定数据来源

    @PropertySource(“classpath:配置文件路径”)

  3. 指定前缀

    使用@ConfigurationProperties(prefix = “前缀”)注解指定前缀

【示例】在模块springboot-04-008中测试

  • mail.properties

    # mail.properties文件
    mail.host=smtp.sina.com
    mail.port=25
    
  • MailConfig.java

    package com.longdidi.config;
    
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.PropertySource;
    
    // 声明为配置类
    @Configuration
    // 指定前缀
    @ConfigurationProperties(prefix = "mail")
    // 用这个注解来指定数据来源
    @PropertySource("classpath:mail.properties")
    public class MailConfig {
        public String host;
    
        public String port;
    
        public String getHost() {
            return host;
        }
    
        public void setHost(String host) {
            this.host = host;
        }
    
        public String getPort() {
            return port;
        }
    
        public void setPort(String port) {
            this.port = port;
        }
    
        @Override
        public String toString() {
            return "MailConfig{" +
                    "host='" + host + '\'' +
                    ", port='" + port + '\'' +
                    '}';
        }
    }
    
  • MailConfigController

    package com.longdidi.controller;
    
    import com.longdidi.config.MailConfig;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class MailConfigController {
    
        @Autowired
        private MailConfig mailConfig;
    
        @RequestMapping("/testMail")
        public String test01() {
            return mailConfig.toString();
        }
    }
    
  • 测试

    http://localhost:8080/testMail

    在这里插入图片描述

4.3.4、读取XML配置

如果项目中有这种老的Spring XML配置文件可以使用@ImportResource(“classpath:xml配置文件路径”)注解可以让XML生效

该注解需要添加到SpringBoot主入口类上

【示例】在模块springboot-04-008中测试

  • applicationContext.xml

    <?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="phone" class="com.longdidi.bean.Phone">
            <property name="size" value="15cm"/>
            <property name="price" value="8000"/>
        </bean>
    
    </beans>
    
  • Phone类

    package com.longdidi.bean;
    
    public class Phone {
        private String size;
        private String price;
    
        public String getSize() {
            return size;
        }
    
        public void setSize(String size) {
            this.size = size;
        }
    
        public String getPrice() {
            return price;
        }
    
        public void setPrice(String price) {
            this.price = price;
        }
    
        @Override
        public String toString() {
            return "Phone{" +
                    "size='" + size + '\'' +
                    ", price='" + price + '\'' +
                    '}';
        }
    }
    
  • 加载xml配置文件

    在Springboot入口程序上添加@ImportResource(“classpath:/applicationContext.xml”)注解来加载xml配置文件

    package com.longdidi;
    
    import com.longdidi.config.App3Config;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    import org.springframework.context.annotation.ImportResource;
    
    @ImportResource("classpath:/applicationContext.xml")
    @EnableConfigurationProperties(App3Config.class)
    @ConfigurationPropertiesScan(basePackages = "com.longdidi.config")
    @SpringBootApplication
    public class Springboot04008Application {
    
        public static void main(String[] args) {
            SpringApplication.run(Springboot04008Application.class, args);
        }
    
    }
    
  • PhoneController

    package com.longdidi.controller;
    
    import com.longdidi.bean.Phone;
    import jakarta.annotation.Resource;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class PhoneController {
    
        @Resource
        Phone phone;
    
        @RequestMapping("/testPhone")
        public String test01() {
            return phone.toString();
        }
    }
    
  • 测试

    http://localhost:8080/testPhone

    在这里插入图片描述

4、配置属性绑定到Bean

SpringBoot配置文件中的信息除了可以使用@Value注解读取之外,也可以将配置信息一次性赋值给Bean对象的属性

将配置项与一个JavaBean绑定起来使用,这样绑定一次就可以随时使用

  • 要绑定的bean需纳入IOC容器管理

    将bean纳入IOC容器管理有以下几种方式

    1. @Component:目的是为了这个JavaBean在项目启动时候被扫描到并加载到Spring容器之中

    2. @Configuration注解:

      @Configuration注解的底层就是@Component,但是二者意义不同

      @Configuration注解侧重配置之意,@Component侧重组件之意

      当然配置也是项目组件之一,在这里要将配置文件属性与JavaBean绑定,当然更侧重配置之意

    3. @EnableConfigurationProperties

      标注在SpringBoot主入口程序上

      指定要加载的配置类文件

    4. @ConfigurationPropertiesScan

      标注在SpringBoot主入口程序上

      指定要扫描的包路径

  • 指定要绑定的属性前缀

    被绑定的bean需要使用@ConfigurationProperties(prefix = "前缀")注解进行标注,prefix用来指定前缀

    可以将其理解为绑定专用注解

    在这里插入图片描述

    它的作用就是将指定的前缀的配置项的值与JavaBean的字段绑定

    注意:为了绑定成功,一般将字段的名称与配置项键的最后一个键名相同,这样整个键在去掉前缀的情况下就和字段名称一致,以此来进行绑定

    在这里插入图片描述

  • bean中的所有属性都提供了setter方法,因为底层是通过setter方法给bean属性赋值的

    在这里插入图片描述

  • 定义属性文件

    在配置文件中根据指定的前缀来定义配置项

将配置与JavaBean绑定之后就可以通过JavaBean来获取配置的内容,而且JavaBean已经被@Component注解或者@Configuration注解加载到Spring容器,可以使用自动注入的方式在其他类中随便使用

4.4.1、四种绑定方式示例

(1)、@Component

因为application.properties文件会被自动加载,也就是说配置项会被自动加载到Spring容器之中,省去了手动加载的配置

在要与属性绑定的JavaBean的类定义顶部加@Component注解和@ConfigurationProperties(prefix=“key”)注解

  • @Component

    目的是为了这个JavaBean可以被SpringBoot项目启动时候被扫描到并加载到Spring容器之中

  • @ConfigurationProperties(prefix=“key”)

    注解加注在JavaBean类定义之上,就是属性绑定注解

    可以将其理解为绑定专用注解

    它的作用就是将指定的前缀的配置项的值与JavaBean的字段绑定,这里要注意,为了绑定的成功,一般将字段的名称与配置项键的最后一个键名相同,这样整个键在去掉前缀的情况下就和字段名称一致,以此来进行绑定

【示例】在模块springboot-04-008中测试

  • application.yml

    # @Component
    app1:
      name: jack1
      age: 30
      email: jack1@123.com
    
  • App1Config.java

    package com.longdidi.config;
    
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.stereotype.Component;
    
    @Component
    @ConfigurationProperties(prefix = "app1")
    public class App1Config {
        private String name;
        private Integer age;
        private String email;
    
        @Override
        public String toString() {
            return "App1Config{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", email='" + email + '\'' +
                    '}';
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    }
    
  • App1ConfigController.java

    package com.longdidi.controller;
    
    import com.longdidi.config.App1Config;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class App1ConfigController {
        @Autowired
        private App1Config app1Config;
    
        @RequestMapping("/testApp1")
        public String test01() {
            return app1Config.toString();
        }
    }
    
  • 测试

    访问http://localhost:8080/testApp1

    在这里插入图片描述

说明:

  1. 被绑定的bean需要使用@ConfigurationProperties(prefix = "app1")注解进行标注,prefix用来指定前缀

    在这里插入图片描述

  2. 配置文件中的nameageemail要和bean对象的属性名nameageemail对应上(属性名相同)

    并且bean中的所有属性都提供了setter方法,因为底层是通过setter方法给bean属性赋值的

    在这里插入图片描述

  3. bean的属性需要是非static的属性

(2)、@Configuration

以上操作中使用了@Component注解进行了标注来纳入IoC容器的管理

也可以使用另外一个注解@Configuration,用这个注解将Bean标注为配置类

@Configuration注解的底层就是@Component,但是二者意义不同

@Configuration注解侧重配置之意,@Component侧重组件之意

当然配置也是项目组件之一,在这里要将配置文件属性与JavaBean绑定,当然更侧重配置之意

多数情况下我们会选择使用这个注解,因为该Bean对象的属性对应的就是配置文件中的配置信息

【示例】在模块springboot-04-008中测试

  • application.yml

    # @Configuration
    app2:
      name: jack2
      age: 30
      email: jack2@123.com
    
  • App2Config.java

    package com.longdidi.config;
    
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @ConfigurationProperties(prefix = "app2")
    public class App2Config {
        private String name;
        private Integer age;
        private String email;
    
        @Override
        public String toString() {
            return "App2Config{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", email='" + email + '\'' +
                    '}';
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    }
    
  • App2ConfigController.java

    package com.longdidi.controller;
    
    import com.longdidi.config.App2Config;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class App2ConfigController {
        @Autowired
        private App2Config app2Config;
    
        @RequestMapping("/testApp2")
        public String test01() {
            return app2Config.toString();
        }
    }
    
  • 测试

    http://localhost:8080/testApp2

    在这里插入图片描述

在这里插入图片描述

(3)、@EnableConfigurationProperties

@EnableConfigurationProperties标注在SpringBoot主入口程序上

指定要加载的配置类文件

在这里插入图片描述

【示例】在模块springboot-04-008中测试

  • application.yml

    # @EnableConfigurationProperties
    app3:
      name: jack3
      age: 30
      email: jack3@123.com
    
  • App3Config.java

    配置类中使用@ConfigurationProperties注解绑定前缀

    package com.longdidi.config;
    
    import org.springframework.boot.context.properties.ConfigurationProperties;
    
    @ConfigurationProperties(prefix = "app3")
    public class App3Config {
        private String name;
        private Integer age;
        private String email;
    
        @Override
        public String toString() {
            return "App3Config{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", email='" + email + '\'' +
                    '}';
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    }
    
  • 启动类配置

    启动类上使用@EnableConfigurationProperties(App3Config.class)指定配置类

    package com.longdidi;
    
    import com.longdidi.config.App3Config;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.context.properties.EnableConfigurationProperties;
    
    @EnableConfigurationProperties(App3Config.class)
    @SpringBootApplication
    public class Springboot04008Application {
    
        public static void main(String[] args) {
            SpringApplication.run(Springboot04008Application.class, args);
        }
    
    }
    
  • App3ConfigController.java

    package com.longdidi.controller;
    
    import com.longdidi.config.App3Config;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class App3ConfigController {
    
        @Autowired
        private App3Config app3Config;
    
        @RequestMapping("/testApp3")
        public String test01() {
            return app3Config.toString();
        }
    }
    
  • 测试

    http://localhost:8080/testApp3

    在这里插入图片描述

(4)、@ConfigurationPropertiesScan

@ConfigurationPropertiesScan标注在SpringBoot主入口程序上

指定要扫描的路径

【测试】在模块springboot-04-008中测试

  • application.yml

    # @ConfigurationPropertiesScan
    app4:
      name: jack4
      age: 30
      email: jack4@123.com
    
  • App4Config.java

    使用@ConfigurationProperties注解配置前缀

    package com.longdidi.config;
    
    import org.springframework.boot.context.properties.ConfigurationProperties;
    
    @ConfigurationProperties(prefix = "app4")
    public class App4Config {
        private String name;
        private Integer age;
        private String email;
    
        @Override
        public String toString() {
            return "App4Config{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", email='" + email + '\'' +
                    '}';
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    }
    
  • 启动类配置

    使用@ConfigurationPropertiesScan注解扫描配置类的路径

    package com.longdidi;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
    
    //@EnableConfigurationProperties(App3Config.class)
    @ConfigurationPropertiesScan(basePackages = "com.longdidi.config")
    @SpringBootApplication
    public class Springboot04008Application {
    
        public static void main(String[] args) {
            SpringApplication.run(Springboot04008Application.class, args);
        }
    
    }
    
  • App4ConfigController.java

    package com.longdidi.controller;
    
    import com.longdidi.config.App4Config;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class App4ConfigController {
    
        @Autowired
        private App4Config app4Config;
    
        @RequestMapping("/testApp4")
        public String test01() {
            return app4Config.toString();
        }
    }
    
  • 测试

    http://localhost:8080/testApp4

    在这里插入图片描述

4.4.2、绑定类型示例

(1)、绑定简单Bean

在这里插入图片描述

【示例】在模块springboot-04-008中测试

  • application.yml

    # 绑定简单bean
    user1:
      name: lucy
      email: lucy@123.com
    
  • User1Config.java

    package com.longdidi.config;
    
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    @ConfigurationProperties(prefix = "user1")
    public class User1Config {
        private String name;
        private String email;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    
        @Override
        public String toString() {
            return "User1Config{" +
                    "name='" + name + '\'' +
                    ", email='" + email + '\'' +
                    '}';
        }
    }
    
  • User1ConfigController.java

    package com.longdidi.controller;
    
    import com.longdidi.config.User1Config;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class User1ConfigController {
    
        @Autowired
        private User1Config user1Config;
    
        @RequestMapping("/testUser1")
        public String test01() {
            return user1Config.toString();
        }
    }
    
  • 测试

    http://localhost:8080/testUser1

    在这里插入图片描述

(2)、绑定嵌套Bean

当一个Bean中嵌套了一个Bean也可以将配置信息绑定到该Bean上

在这里插入图片描述

【示例】在模块springboot-04-008中测试

  • application.yml

    # 绑定嵌套bean
    person:
      name: lucy
      email: lucy@123.com
      address:
        city: BJ
        street: ChaoYang
    
  • Person.java

    package com.longdidi.bean;
    
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration(proxyBeanMethods = false)
    @ConfigurationProperties(prefix = "person")
    public class Person {
        private String name;
        private String email;
        private Address address;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    
        public Address getAddress() {
            return address;
        }
    
        public void setAddress(Address address) {
            this.address = address;
        }
    
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", email='" + email + '\'' +
                    ", address=" + address +
                    '}';
        }
    }
    
  • Address.java

    package com.longdidi.bean;
    
    public class Address {
        private String city;
        private String street;
    
        public String getCity() {
            return city;
        }
    
        public void setCity(String city) {
            this.city = city;
        }
    
        public String getStreet() {
            return street;
        }
    
        public void setStreet(String street) {
            this.street = street;
        }
    
        @Override
        public String toString() {
            return "Address{" +
                    "city='" + city + '\'' +
                    ", street='" + street + '\'' +
                    '}';
        }
    }
    
  • PersonConfigController.java

    package com.longdidi.controller;
    
    import com.longdidi.bean.Person;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class PersonConfigController {
    
        @Autowired
        private Person person;
    
        @RequestMapping("/testPerson")
        public String test01() {
            return person.toString();
        }
    }
    
  • 测试

    http://localhost:8080/testPerson

    在这里插入图片描述

(3)、绑定到Map/List/Array

绑定时要看除去前缀以后,剩下的部分每个层级是什么数据类型,就在JavaBean中对应的层级定义什么样的数据类型

在这里插入图片描述

【示例】在模块springboot-04-008中测试

  • application.yml

    # 绑定到Map/list/数组
    more:
      data:
        # 数组第一种形式:数组中元素是简单类型
        names1:
          - tom2
          - smith2
        # 数组第二种形式:数组中元素是简单类型
        names2: [jack, lucy]
    
        # 数组中元素是bean
        #  addrArray:
        addr-array:
          - city: BeiJing2
            street: ChaoYang2
          - city: TianJin2
            street: NanKai2
    
        # List集合:集合中的元素是bean
        #  addrList:
        addr-list:
          - city: BeiJing_List2
            street: ChaoYang_List2
          - city: TianJin_List2
            street: NanKai_List2
    
        # Map集合:String,Bean
        addrs:
          addr1:
            city: BeiJing_Map2
            street: ChaoYang_Map2
          addr2:
            city: TianJin_Map2
            street: NanKai_Map2
    
  • More1Config.java

    package com.longdidi.config;
    
    import com.longdidi.bean.Address;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.Map;
    
    @ConfigurationProperties(prefix = "more.data")
    public class More1Config {
        // 组第一种形式:数组中元素是简单类型
        private String[] names1;
    
        // 数组第二种形式:数组中元素是简单类型
        private String[] names2;
    
        // 数组:数组中元素是bean
        private Address[] addrArray;
    
        // List集合:集合中的元素是bean
        private List<Address> addrList;
    
        // Map集合:String,Bean
        private Map<String, Address> addrs;
    
        public String[] getNames1() {
            return names1;
        }
    
        public void setNames1(String[] names1) {
            this.names1 = names1;
        }
    
        public String[] getNames2() {
            return names2;
        }
    
        public void setNames2(String[] names2) {
            this.names2 = names2;
        }
    
        public Address[] getAddrArray() {
            return addrArray;
        }
    
        public void setAddrArray(Address[] addrArray) {
            this.addrArray = addrArray;
        }
    
        public List<Address> getAddrList() {
            return addrList;
        }
    
        public void setAddrList(List<Address> addrList) {
            this.addrList = addrList;
        }
    
        public Map<String, Address> getAddrs() {
            return addrs;
        }
    
        public void setAddrs(Map<String, Address> addrs) {
            this.addrs = addrs;
        }
    
        @Override
        public String toString() {
            return "More1Config{" +
                    "names1=" + Arrays.toString(names1) +
                    ", names2=" + Arrays.toString(names2) +
                    ", addrArray=" + Arrays.toString(addrArray) +
                    ", addrList=" + addrList +
                    ", addrs=" + addrs +
                    '}';
        }
    }
    
  • Address.java

    package com.longdidi.bean;
    
    public class Address {
        private String city;
        private String street;
    
        public String getCity() {
            return city;
        }
    
        public void setCity(String city) {
            this.city = city;
        }
    
        public String getStreet() {
            return street;
        }
    
        public void setStreet(String street) {
            this.street = street;
        }
    
        @Override
        public String toString() {
            return "Address{" +
                    "city='" + city + '\'' +
                    ", street='" + street + '\'' +
                    '}';
        }
    }
    
  • More1ConfigController

    package com.longdidi.controller;
    
    import com.longdidi.config.More1Config;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class More1ConfigController {
    
        @Autowired
        private More1Config more1Config;
    
        @RequestMapping("/testMore1")
        public String test01() {
            return more1Config.toString();
        }
    }
    
  • 测试

    http://localhost:8080/testMore1

    在这里插入图片描述

(4)、绑定到第三方对象

将配置文件中的信息绑定到某个Bean对象上,如果这个Bean对象没有源码,是第三方库提供的,此时可以单独编写一个方法,在方法上使用以下两个注解进行标注:

  • @Bean
  • @ConfigurationProperties

在这里插入图片描述

【示例】在模块springboot-04-008中测试

假设有这样一个类Street,代码如下:

package com.longdidi.bean;

public class Street {
    private String city;
    private String street;

    public void setCity(String city) {
        this.city = city;
    }

    public void setStreet(String street) {
        this.street = street;
    }

    @Override
    public String toString() {
        return "Street{" +
                "city='" + city + '\'' +
                ", street='" + street + '\'' +
                '}';
    }
}

当然这里是模拟的,应该看不到这个类的源码,只知道有这样一个字节码Street.class。也可以看到这个Street类上没有添加任何注解

假设要将以下配置绑定到这个Bean上

# 绑定到源码
other:
  abc:
    city: BEIJING
    street: tongzhouqu

实现代码如下

package com.longdidi.config;

import com.longdidi.bean.Street;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

// 指定该类是一个配置类
@Configuration
public class StreetConfig {
    // 假设Street类是第三方库提供的类,使用以下方式可以完成配置到bean的属性的绑定
    // 纳入IoC容器的管理
    @Bean
    // 将配置文件中凡是以 other.abc 开头的配置数据绑定到Street对象的属性上
    @ConfigurationProperties(prefix = "other.abc")
    public Street street() {
        return new Street();
    }

}

编写测试类

package com.longdidi.controller;

import com.longdidi.config.StreetConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class StreetConfigController {
    @Autowired
    StreetConfig streetConfig;

    @RequestMapping("/testStreet")
    public String test01() {
        return streetConfig.street().toString();
    }
}

测试http://localhost:8080/testStreet

在这里插入图片描述

4.4.3、自定义配置绑定到Bean

之前所讲的内容是将Spring Boot框架默认的配置文件application.propertiesapplication.yml作为数据的来源绑定到Bean上

如果是自定义的配置文件,可以使用@PropertySource注解指定配置文件的位置,这个配置文件可是.properties,也可以是.xml

配置类需要使用三个注解标注

  • @Configuration:指定该类为配置类,纳入Spring容器的管理
  • @ConfigurationProperties(prefix = “group”):将配置文件中的值赋值给Bean对象的属性
  • @PropertySource(“classpath:a/b/group-info.properties”):指定额外的配置文件

【示例】在模块springboot-04-008中测试

  1. 创建配置文件

    resources目录下新建a目录,在a目录下新建b目录,b目录中新建group-info.properties文件,进行如下的配置

    group.name=IT
    group.leader=LaoDu
    group.count=20
    
  2. 定义Java类Group,然后进行注解标注

    package com.longdidi.config;
    
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.PropertySource;
    
    // 声明为配置类
    @Configuration
    // 指定前缀
    @ConfigurationProperties(prefix = "group")
    // 用这个注解来指定数据来源
    @PropertySource("classpath:/a/b/group-info.properties")
    public class GroupConfig {
        private String name;
        private String leader;
        private Integer count;
    
        @Override
        public String toString() {
            return "GroupConfig{" +
                    "name='" + name + '\'' +
                    ", leader='" + leader + '\'' +
                    ", count=" + count +
                    '}';
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public void setLeader(String leader) {
            this.leader = leader;
        }
    
        public void setCount(Integer count) {
            this.count = count;
        }
    }
    
  3. 创建测试类

    package com.longdidi.controller;
    
    import com.longdidi.config.GroupConfig;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    @RestController
    public class GroupConfigController {
        @Autowired
        GroupConfig groupConfig;
    
        @RequestMapping("/testGroup")
        public String test01() {
            return groupConfig.toString();
        }
    }
    
  • 测试

    http://localhost:8080/testGroup

    在这里插入图片描述

5、配置文件合并

一个项目中所有的配置全部编写到application.properties文件中会导致配置臃肿、不易维护

有时我们会将配置编写到不同的文件中

例如:application-mysql.properties专门配置mysql的信息,application-redis.properties专门配置redis的信息,最终将两个配置文件合并到一个配置文件中

4.5.1、properties文件合并

可以使用spring.config.import来加载多个properties配置文件

【示例】在springboot-04-009模块中测试

  • 定义application-mysql.properties属性文件

    spring.datasource.username=root
    spring.datasource.password=123456
    
  • 定义application-redis.properties属性文件

    spring.data.redis.host=localhost
    spring.data.redis.port=6379
    
  • 定义application.properties属性文件

    spring.config.import=classpath:application-mysql.properties,classpath:application-redis.properties
    
  • 编写配置类

    package com.longdidi.config;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class AppConfig {
        @Value("${spring.datasource.username}")
        private String mysqlUsername;
        @Value("${spring.datasource.password}")
        private String mysqlPassword;
        @Value("${spring.data.redis.host}")
        private String redisHost;
        @Value("${spring.data.redis.port}")
        private String redisPort;
    
        public void printInfo() {
            System.out.println(mysqlUsername + "," + mysqlPassword + "," + redisHost + "," + redisPort);
        }
    }
    
  • 编写单元测试

    package com.longdidi;
    
    import com.longdidi.config.AppConfig;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    @SpringBootTest
    class Tests01 {
    
        @Autowired
        private AppConfig appConfig;
    
        @Test
        void test01() {
            appConfig.printInfo();
        }
    
    }
    
  • 测试

    在这里插入图片描述

4.5.2、yml文件合并

在yml文件中可以使用如下配置合并多个配置文件

spring:
  config:
    import:
      - classpath:配置文件1.yml
      - classpath:配置文件2.yml

【示例】在springboot-04-009模块中测试

  • 定义application-mysql.yml属性文件

    spring:
      datasource:
        username: rootyml
        password: 123456yml
    
  • 定义application-redis.yml属性文件

    spring:
      data:
        redis:
          host: localhostyml
          port: 6379
    
  • 定义application.yml属性文件

    spring:
      config:
        import:
          - classpath:/config/application-mysql.yml
          - classpath:/config/application-redis.yml
    #    import: [classpath:/config/application-mysql.yml, classpath:/config/application-redis.yml]
    
  • 编写配置类

    package com.longdidi.config;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Configuration;
    
    @Configuration
    public class AppConfig {
        @Value("${spring.datasource.username}")
        private String mysqlUsername;
        @Value("${spring.datasource.password}")
        private String mysqlPassword;
        @Value("${spring.data.redis.host}")
        private String redisHost;
        @Value("${spring.data.redis.port}")
        private String redisPort;
    
        public void printInfo() {
            System.out.println(mysqlUsername + "," + mysqlPassword + "," + redisHost + "," + redisPort);
        }
    }
    
  • 编写单元测试

    package com.longdidi;
    
    import com.longdidi.config.AppConfig;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    @SpringBootTest
    class Tests02 {
    
        @Autowired
        private AppConfig appConfig;
    
        @Test
        void test01() {
            appConfig.printInfo();
        }
    
    }
    
  • 测试

    在这里插入图片描述

6、多环境切换

在Spring Boot中多环境配置文件名需要满足application-{profile}.properties的格式,其中{profile}对应你的环境标识

比如

application-dev.properties:开发环境

application-prod.properties:生产环境

想要使用对应的环境,可以通过下面的方式设置

  • 配置文件方式

    在application.properties中使用spring.profiles.active属性来设置,值对应上面提到的{profile},这里就是指dev、prod这2个

  • 启动参数方式

    命令行启动的时候带上参数

    java -jar xxx.jar --spring.profiles.active=dev

  • 注解指定

在Spring Boot中,多环境切换是指在一个应用程序中支持多种运行环境配置的能力

这通常用于区分开发(development)、测试(testing)、预生产(staging)和生产(production)等不同阶段的环境。

这种功能使得开发者能够在不同的环境中使用不同的配置,比如数据库连接信息、服务器端口、环境变量等,而不需要更改代码。这对于维护一个可移植且易于管理的应用程序非常重要。

在Spring Boot中多环境配置文件名需要满足application-{profile}.properties的格式,其中{profile}对应你的环境标识

比如

application-dev.properties:开发环境

application-prod.properties:生产环境

想要使用对应的环境,可以通过下面的方式设置

  • 配置文件方式

    在application.properties中使用spring.profiles.active属性来设置,值对应上面提到的{profile},这里就是指dev、prod这2个

  • 启动参数方式

    命令行启动的时候带上参数

    java -jar xxx.jar --spring.profiles.active=dev

使用步骤

  • 使用“spring.config.activate.on-profile”或者“spring. profiles”指定当前环境的名称
  • 使用“spring.profiles.active”指定要使用哪个环境
  • 使用“—”定义一组配置,可以定义多组配置

在这里插入图片描述

4.6.1、单个配置文件方式

【示例】springboot-04-010模块测试

  • aplication.yml

    spring:
      profiles:
        active: proc   # 指定要使用哪一个环境
    
    ---
    server:
      port: 8081
    spring:
      #profiles: dev  # 用 spring.profiles 设置配置文件的名称,是开发环境
      config:
        activate:
          on-profile: dev
    
    ---
    server:
      port: 8082
    spring:
      #profiles: test  # 用 spring.profiles 设置配置文件的名称,是测试环境
      config:
        activate:
          on-profile: test
    ---
    server:
      port: 8083
    spring:
      #profiles: proc  # 用 spring.profiles 设置配置文件的名称,是生产环境
      config:
        activate:
          on-profile: proc
    
  • Test01.java

    package com.longdidi;
    
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.test.context.SpringBootTest;
    
    @SpringBootTest
    class Test01 {
    
        @Value("${server.port}")
        private String port;
    
        @Test
        void testValue() {
            System.out.println("启动端口:" + port);
        }
    
    }
    
  • 测试结果

    在这里插入图片描述

4.6.2、多个配置文件方式

(1)、Active激活环境

【示例】springboot-04-010模块测试

在类路径下创建config目录,在config目录下创建application.yml、application-dev.yml、application-test.yml文件

  • application.yml

    spring:
      profiles:
        active: dev   # 指定要使用哪一个环境
    
  • application-dev.yml

    env: dev环境
    
  • application-test.yml

    env: test环境
    
  • Test02.java

    package com.longdidi;
    
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.test.context.SpringBootTest;
    
    @SpringBootTest
    class Test02 {
    
        @Value("${env}")
        private String env;
    
        @Test
        void testValue() {
            System.out.println("当前环境:" + env);
        }
    
    }
    
  • 测试

    在这里插入图片描述

(2)、Include加载其它配置
  • 根据功能对配置文件中的信息进行拆分,并制作成独立的配置文件,命名规则如下

    1. application-devDB.yml
    2. application-devRedis.yml
    3. application-devMVC.yml
  • 使用include属性加载其它配置

    1. 多个环境间使用逗号分隔

    2. 环境间的加载顺序是“include”配置的属性文件+“主文件”

    3. 当主环境dev与其他环境有相同属性时,主环境属性生效

    4. 其他环境中有相同属性时,最后加载的环境属性生效

【示例】在测试模块springboot-04-11中进行

application.yml
server:
  port: 8080
spring:
  profiles:
    active: dev
    include: devDb,devRedis
application-dev.yml
env: dev文件
application-devDb.yml
env: db文件
address: 保定市
application-devRedis.yml
env: redis文件
address: 北京市
单测类
package com.longdidi;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class Test01 {
    @Value("${env}")
    private String env;

    @Value("${address}")
    private String address;

    @Test
    void testValue() {
        System.out.println("环境变量:" + env);
        System.out.println("地址:" + address);
    }

}
测试结果

在这里插入图片描述

(3)、Group分组
  • 根据功能对配置文件中的信息进行拆分,并制作成独立的配置文件,命名规则如下

    1. application-devDB.yml
    2. application-devRedis.yml
    3. application-devMVC.yml
  • 使用group分组

    从SpringBoot2.4版开始使用group属性替代include属性,降低了配置书写量

    1. 多个环境间使用逗号分隔
    2. 环境间的加载顺序是“主文件”+“include”配置的属性文件
    3. 使用group属性定义多种主环境与子环境的包含关系
    4. 环境中有相同属性时,最后加载的环境属性生效

    在这里插入图片描述

【示例】在模块springboot-04-012中测试

application.yml
server:
  port: 8080
spring:
  profiles:
    active: dev
    group:
      "dev": devDb,devRedis
      "test": devDb,devRedis
      "pro": devDb,devRedis
application-dev.yml
env: dev文件
application-devDb.yml
env: db文件
address: 保定市
application-devRedis.yml
env: redis文件
address: 北京市
单测类
package com.longdidi;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class Test01 {
    @Value("${env}")
    private String env;

    @Value("${address}")
    private String address;

    @Test
    void testValue() {
        System.out.println("====================================>环境变量:" + env);
        System.out.println("====================================>地址:" + address);
    }
}
测试结果

在这里插入图片描述

7、外部化配置

(1)、什么是外部化配置

外部化配置是指将配置信息存储在应用程序代码之外的地方,这样配置信息可以独立于代码进行管理,这样方便了配置的修改并且修改后不需要重新编译代码、也不需要重新部署项目

(2)、外部化配置的方式

SpringBoot支持多种外部化配置方式,包括但不限于

  • properties文件
  • YAML文件
  • 系统环境变量
  • 命令行参数

(3)、外部化配置的优势

  1. 灵活性:配置文件可以独立于应用程序部署,这使得可以根据运行环境的不同来调整配置,而无需修改代码
  2. 易于维护:配置变更不需要重新构建和部署应用程序,降低了维护成本
  3. 安全性:敏感信息如数据库密码、API密钥等可以存储在外部,并且可以限制谁有权限访问这些配置信息
  4. 共享性:多实例或多服务可以共享相同的配置信息,减少重复配置的工作量
  5. 版本控制:配置文件可以存放在版本控制系统中,便于跟踪历史版本和回滚配置

总之外部化配置使得配置更加灵活、安全、易于管理和共享,是现代云原生应用中非常推荐的做法

(4)、外部化配置对比传统配置

在传统的SSM三大框架中如果修改XML的配置后需要对应用重新打包、重新部署

使用SpringBoot框架的外部化配置后,修改配置后不需要对应用重新打包、也不需要重新部署,最多重启一下服务即可

(5)、外部配置与内部配置顺序

外部化的配置优先级高于内部化配置

这是因为使用外部化配置更加方便

修改外部化配置后无需重新编译、打包、部署,只要重新启动应用即可

(6)、外部化配置测试

创建springboot-04-13模块

打包方式设置为jar包方式

不需要做任何改动,直接启动项目查看控制台输出的端口号(默认使用8080端口)

在这里插入图片描述

将项目打成jar包

在这里插入图片描述

将jar包拷贝到其它任何地方,比如我这里拷贝到"I:\testjar"目录下

在该目录下创建application.properties(或application.yml)配置文件,在配置文件中指定一些属性(这里指定端口号为8083)

打开DOS窗口,进入到"I:\testjar"目录下,使用"jar -jar springboot-04-013-0.0.1-SNAPSHOT.jar"命令启动

在这里插入图片描述

8、配置加载优先级

Spring Boot是基于jar包运行的,打成jar包的程序可以直接通过下面命令运行

java -jar xxx.jar

可以通过以下命令修改tomcat端口号

java -jar xx.jar --server.port=9090

可以看出命令行中连续的两个减号“–”就是对application.properties中的属性值进行赋值的标识

所以“java -jar xx.jar --server.port=9090”等价于在application.properties中添加属性“server.port=9090”

如果怕命令行有风险可以使用SpringApplication.setAddCommandLineProperties(false)禁用它

实际上Spring Boot应用程序有多种途径可以获取配置的属性值

这些方式优先级如下

  1. 命令行参数
  2. SPRING_APPLICATION_JSON中的属性(环境变量或系统属性中的内联JSON嵌入)
  3. ServletConfig初始化参数
  4. ServletContext初始化参数
  5. 来自java:comp/env的JNDI属性
  6. JVM系统属性(System.getProperties())
  7. 操作系统环境变量
  8. RandomValuePropertySource配置的random.*属性值
  9. jar外部的application-{profile}.properties或application.yml(带spring.profile)配置文件
  10. jar内部的application-{profile}.properties或application.yml(带spring.profile)配置文件
  11. jar外部的application.properties或application.yml(不带spring.profile)配置文件
  12. jar内部的application.properties或application.yml(不带spring.profile)配置文件
  13. @Configuration注解类上的@PropertySource
  14. 通过SpringApplication.setDefaultProperties指定的默认属性
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值