全面理解SpringBoot的配置文件

    科技2022-08-09  102

    1 什么是配置文件

    指main-resources-Application.properties或Application.yml文件,这两个都是全局配置文件若不存在则new file新建用于修改自动配置的默认值

    2 YAML语言

    是一种用于配置文件的标记语言

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

    语法

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

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

    区分大小写

    value的书写

    普通变量:Key: value

    双引号,不会转义特殊字符。\n表示回车单引号,会转义,\n是普通字符串

    对象:用缩进写属性

    缩进写法

    行内写法

    数组:用-表示一个元素

    缩进写法

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

    PS:写的时候可以注意下面的提示

    3 配置文件应用实例:设置端口值

    new java class: bean.Person

    new Java class :Dog

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

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

    <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>

    写好person的配置文件application.yml

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

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

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

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

    在person类前面加上@Component

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

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

    这里本来应该是@Autowired,但是出现错误。修改成@Autowired(required=false)解决。

    运行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配置文件的写法

    普通语法:

    在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 …选项

    随机数的写法: person.last-name=kris${random.uuid} person.age=${random.int} 为变量设置默认值: 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:

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

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

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

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

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

    7 profile 多配置文件

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

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

    实现方法1:

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

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

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

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

    在application.yml ,用---表示分割,上面叫document1,下面是document2,同理分割多个指定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个位置,同理也有“优先级顺序+覆盖+互补”

    其中较为重要的有:

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

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

    来自java:comp/env的JNDI属性

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

    操作系统环境变量

    RandomValuePropertySource配置的random.*属性值

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

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

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

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

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

    @Configuration注解类上的@PropertySource

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

    9 @Conditional组件

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

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

    在application.properties写上debug=true

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

    Processed: 0.016, SQL: 9