全面理解SpringBoot的配置文件

1 什么是配置文件
  • main-resources-Application.propertiesApplication.yml文件,这两个都是全局配置文件
  • 若不存在则new file新建
  • 用于修改自动配置的默认值
2 YAML语言
  • 是一种用于配置文件的标记语言

  • 以前的配置文件一般用xml,而YAML以数据为中心(没有那么多开闭标签)

  • 语法

    • key:value表示一个键值对,冒号和value之间必须有空格

    • 空格控制缩进来控制层级关系(那么只要左对齐就是同级)

    • 区分大小写

    • value的书写

      • 普通变量:Key: value

        • 双引号,不会转义特殊字符。\n表示回车
        • 单引号,会转义,\n是普通字符串
      • 对象:用缩进写属性

        • 缩进写法
          在这里插入图片描述

        • 行内写法
          在这里插入图片描述

      • 数组:用-表示一个元素

        • 缩进写法
          在这里插入图片描述

        • 行内写法
          ​ Pets: [cat,dog,pig]

PS:写的时候可以注意下面的提示
在这里插入图片描述

3 配置文件应用实例:设置端口值
  1. new java class: bean.Person

  2. new Java class :Dog

  3. 定义Person类和Dog类【Alt+insert键,可以一键导入get/set/toString方法】

  4. 在pom里面导入配置文件处理器的依赖项(不然会not found错误)

    <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-configuration-processor</artifactId>
         <optional>true</optional>
    </dependency>
    
  5. 写好person的配置文件application.yml

  6. 把配置文件的值绑定到java类中

    • person类前面加入:@ConfiguationProperties(perfix="person")

      ——告诉springboot,本类所有的属性都是由配置文件确定

      ——perfix,确定将配置文件中哪个属性进行一一映射

    • 在person类前面加上@Component

      ——因为还要是组件内的容器,才能使用容器提供的ConfiguationProperties

  7. 在测试单元里面,注入person,看测试容器收到的person是不是配置文件设置的

    这里本来应该是@Autowired,但是出现错误。修改成@Autowired(required=false)解决。
    在这里插入图片描述

  8. 运行contextLoads()函数,控制台打印出person的信息如下:

    可见,与配置文件的设置相同。

    ==【图片】==

附代码:

Person.java

package com.atguigu.springboot02config.bean;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.Map;

@Component
@ConfigurationProperties(prefix = "person")
public class Person {
    private String lastName;
    private Integer age;
    private boolean boss;
    private Date birth;

    private Map<String,Object> maps;
    private List<Object> lists;

    private Dog dog;

    @Override
    public String toString() {
        return "person{" +
                "lastName='" + lastName + '\'' +
                ", age=" + age +
                ", boss=" + boss +
                ", birth=" + birth +
                ", maps=" + maps +
                ", lists=" + lists +
                ", dog=" + dog +
                '}';
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public boolean isBoss() {
        return boss;
    }

    public void setBoss(boolean boss) {
        this.boss = boss;
    }

    public Date getBirth() {
        return birth;
    }

    public void setBirth(Date birth) {
        this.birth = birth;
    }

    public Map<String, Object> getMaps() {
        return maps;
    }

    public void setMaps(Map<String, Object> maps) {
        this.maps = maps;
    }

    public List<Object> getLists() {
        return lists;
    }

    public void setLists(List<Object> lists) {
        this.lists = lists;
    }

    public Dog getDog() {
        return dog;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }
}

Dog.java

package com.atguigu.springboot02config.bean;

public class Dog {
    private String Name;
    private Integer age;

    @Override
    public String toString() {
        return "Dog{" +
                "Name='" + Name + '\'' +
                ", age=" + age +
                '}';
    }

    public String getName() {
        return Name;
    }

    public void setName(String name) {
        Name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }
}

application.yml

person:
  lastName: zhangsan
  age: 90
  boss: false
  birth: 2020/10/1
  maps: {k1: v1,k2: v2}
  lists:
    - lisi
    - zhaoliu
  dog:
    name: wawa
    age: 2

SpringBoot02ConfigApplicationTests.java

package com.atguigu.springboot02config;

import com.atguigu.springboot02config.bean.Person;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.awt.*;

@RunWith(SpringRunner.class)
@SpringBootTest
class SpringBoot02ConfigApplicationTests<person> {

    @Autowired(required = false)
    Person person;

    @Test
    void contextLoads() {
        System.out.println(person);
    }

}
4 properties配置文件的写法
  1. 普通语法:

在application.properties里写入:

person.last-name=xxx
person.age=18
person.birth=2017/10/10
person.boss=false
person.maps.k1=v1
person.k2=14
person.lists=a,b,c
person.dog.name=doggie
person.dog.age=1

设置好后,同样运行contextLoads()函数,也可以得到正确的person

但是会有中文乱码问题,解决方法:

在idea-setting-搜索file encoding-下方选择UTF-8-勾选Transparent …选项

  1. 随机数的写法:
person.last-name=kris${random.uuid}
person.age=${random.int}
  1. 为变量设置默认值:
person.dog.name=${person.hello:hello}_dog

${person.hello:hello}_dog:如果没有设置过person.hello这个东西,就会原样打印:{person.hello}_dog

${person.hello:hello}_dog:没有设置过person.hello这个东西,person.hello就会变成默认值hello,总体打印成hello_dog

5 @Value

之前的yml和properties都是用了@ConfiguationProperties注解,而除此之外还可以使用@Value注解

如:

@Component
public class Person{
	@Value("${person.last-name}")
	private String lastName;

	@Value("#{11*2}")
	private Integer age;
}

得到age=22

二者区别如下:

@ConfiguationProperties@Value
注入批量设置变量值一个个指定
松散绑定×
spEL×(不可计算)
JSR303数据校验×
复杂类型(如map)
  • 松散绑定:就是支持下面几种写法意义一样

==【图片】==

  • spEL(就是能不能计算)

==【代码】==

  • JSR303数据校验:指可以加上一个@Validated表示要校验某个变量的格式,如@Email表示某个变量必须是邮箱格式,格式错误就会报错
6 加载指定的配置文件

刚刚都是加载全局配置文件application.properties,现在想加载别的文件来当配置文件

方法1:

  1. 在resources文件夹-新建文件person.properties
  2. @PropertySource(value={classpath:person.properties}):加载指定配置文件

更推荐的方法(全注解方法):

  1. 添加配置类:在com下,new java class- config.MyAppConfig
  2. @Configuration 表明当前类是配置类,相当于配置文件
  3. @Bean 将方法的返回值添加到容器中

==【图片】==

这是使用配置类给容器添加组件(将方法的返回值添加到容器中),在容器中标识组件的默认id是方法的方法名(helloService)

测试容器中有没有“helloService”这个组件

==【图片】==

7 profile 多配置文件

在生产、开发、测试不同环境下,可能需要不同的配置文件来实现不同的配置

而主程序默认使用的是application.properties的配置

实现方法1:

  1. 在resources文件夹新建application-pro.properties(pro环境模拟),application-dev.properties(dev环境模拟),application-test.properties(test环境模拟)

    (注意:格式得是application-xxx.properties或者application-xxx.yml

  2. 在全局配置application.properties头上写spring.profiles.active=dev,指定哪个环境被激活

实现方法2(文档块方式):

  1. application.yml ,用---表示分割,上面叫document1,下面是document2,同理分割多个
  2. 指定spring.profiles.active=dev,如以下代码,运行的就是dev环境的端口,否则默认8081
server:
	port: 8081
spring:
	profiles:
		active: dev
---
server:
	port: 8083
spring:
	profiles: dev
---
server:
	port: 8084
spring:
	profiles: pro
8 配置文件加载位置
8.1 内部配置文件

springboot会识别以下四个位置的配置文件,而且是按优先级高到低依次往下

在这里插入图片描述

  • file指项目的根目录
  • classpath指的是类路径,这里是main-resources

识别的时候会覆盖+互补配置

  • 覆盖:高优先级和低优先级都有,只采用高优先级的(但是也会加载低的)
  • 互补配置:指如果在高优先级没有配置的话会采用低优先级的配置

项目打包好以后启动时,可以使用命令行参数的形式来指定配置文件的新位置,这时候指定的配置文件和默认加载的配置文件共同起作用形成互补配置;

——用于运维,已经打包好了不需要重新打包

8.2 外部配置文件

配置还可以写在这17个位置,同理也有“优先级顺序+覆盖+互补”

==【图片】==

其中较为重要的有:

  1. 命令行形式直接修改配置:

    多个参数之间用空格隔开,如–server=… --path=…

==【图片】==

  1. 来自java:comp/env的JNDI属性

  2. Java系统属性(System.getProperties())

  3. 操作系统环境变量

  4. RandomValuePropertySource配置的random.*属性值

【由jar包外向jar包内进行寻找; 优先加载带profile,再来加载不带profile】

  1. jar包外部的application-{profile}.properties或application.yml(带spring.profile)配置文件

  2. jar包内部的application-{profile}.properties或application.yml(带spring.profile)配置文件

  3. jar包外部的application.properties或application.yml(不带spring.profile)配置文件

  4. jar包内部的application.properties或application.yml(不带spring.profile)配置文件

  5. @Configuration注解类上的@PropertySource

  6. 通过SpringApplication.setDefaultProperties指定的默认属性
    所有支持的配置加载来源;

9 @Conditional组件

有些组件需要设置成在特定条件下生效。
@Conditional这个组件为配置的生效设置了条件,如下表:

==【图片】==

那怎么更方便的知道哪些配置生效?

  1. application.properties写上debug=true

  2. 控制台打印信息中,Positive matches 表示生效的,Negetive matches表示没有生效的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值