SpringBoot配置文件

SpringBoot项目不同于SSM框架繁多的配置文件,生成项目时若没有特殊需要,一般只需要一个配置文件,默认在项目根目录下生成一个application.properties文件,但官方更加推荐我们使用另一格式,也就是yml格式的文件。

YAML语法

配置文件的作用

之前有说到,SpringBoot的自动装配已经帮我们默认配置好了许多参数,但有时候我们需要自定义一些参数,不想使用默认的,在配置文件中重新填写即可。例如,SpringBoot默认配置项目的运行端口号为8080,在配置文件中我们可以修改:

server:
  port: 8081

此处使用的便是yaml写法,接下来看看什么是yaml语法

YAML语法简介

yml是YAML(YAML Ain’t Markup Language)语言的文件,以数据为中心,比properties、xml等更适合做配置文件。
与properties文件语法不同,yaml语法使用的是K: V的方式,对空格极其敏感,以属性name为例,下面看看两者的不同:

  • properties文件
name=fengjian
  • yaml文件
 port: 8081

再看看与xml文件相比,yml体现出来的简洁性:

  • XML配置端口号
<server>
    <port>8081<port>
server>
  • YAML配置端口号
server:
  prot: 8080

基础语法

  1. 空格十分重要,不能省略
  2. 用缩进代表层级关系,左边对齐的数据代表同一级
  3. 属性和值的大小写敏感

例如一名学生的姓名和年龄:

student:
 name: fengjian
 age: 18

姓名与年龄归属于学生这一对象下的同级属性,两者对齐代表同一级,空格代表属于student下的一级

数据类型

  • 字符串、数字、布尔类型都是k: v形式,字符串不需要带引号
  • list、set中的每一个元素用- 值表示,可以用行内写法[p1,p2,p3]
  • map使用{k1:v1,k2: v2}表示
student:
 name: fengjian # 字符串
 age: 18 # 数字
 graduated: false # Boolean
 birth: 2021/01/01 10:20:12 # 时间
 skill: # list
 	-1 
 	-2 
 subject: [set1,set2] # set
 family: {key1: value1,key2: value2} # map

注意:

  • “ ” 双引号,不会转义字符串里面的特殊字符 ,特殊字符会作为本身想表示的意思;
    比如 :name: “feng \n jian” 输出 :feng 换行 jian
  • ‘’ 单引号,会转义特殊字符 , 特殊字符最终会变成和普通字符一样输出
    比如 :name: ‘feng \n jian’ 输出 :feng \n jian

同样可以使用行内写法:

student: {name: fengjian,age: 3,birth: 2021/01/01 10:20:12}

在SpringBoot项目中注入yml文件

与其他配置文件不同,yml文件可以直接将其中的值注入到类中。首先在项目根目录下编写一个application.yml文件

注入实体类

编写一个实体类Dog,并写好构造器、getset方法,并将其注入到Spring容器中:

@Component //注入到Spring容器中
public class Dog {
   private String firstName;
   
   private Integer age;
 }

利用spring中的注解@Value,在属性上方也能对他们进行赋值:

  @Value("旺财")
  private String firstName;
  @Value("1")
  private Integer age;

  public Dog() {
  }

在测试类中进行测试:
SpringBoot配置文件_第1张图片

SpringBoot配置文件_第2张图片
而在使用了yaml后,可以直接从配置文件中读取值,此时再新建一个person类:

@Component
public class Person {
    private String name;
    private Integer age;
    private Boolean happy;
    private Date birth;
    private Map<String,Object> maps;
    private List<Object> list;
    private Dog dog;
 }

在yml文件中编写对应的person对象:

person:
  name: fengjian
  age: 18
  happy: false
  birth: 2021/7/17
  maps: {k1: v1,k2: v2}
  hello: happy
  list:
    - program
    - music
  dog:
    name: 旺财
    age: 3

在实体类中加入@ConfigurationProperties注解,将类与配置文件关联起来:

@Component
@ConfigurationProperties(prefix = "person")
/*
@ConfigurationProperties作用:
将配置文件中配置的每一个属性的值,映射到这个组件中;
告诉SpringBoot将本类中的所有属性和配置文件中相关的配置进行绑定
参数 prefix = “person” : 将配置文件中的person下面的所有属性一一对应
*/
public class Person {
}

同样在测试类中测试:
SpringBoot配置文件_第3张图片
在这里插入图片描述

加载指定的配置文件

在上述例子中,我们使用@ConfigurationProperties(prefix="")将实体类与配置文件中指定的对象绑定,实现了从全局配置文件(application.yml)读取值。但有时我们希望全局配置文件中只配置一些项目相关的参数,其他参数放在其他配置文件中,那么此时就需要通过加载指定的配置文件来完成了,我们需要用到另一个注解@PropertySource 。

我们新建一个application.properties文件,注意先检查一下.properties文件的编码格式:
SpringBoot配置文件_第4张图片

接着在里面放一个变量name:
SpringBoot配置文件_第5张图片
此时我想将name赋值到Person类的name中,那么在Person类的头部加上@PropertySource注解:

@PropertySource(value = "classpath:/application.properties")
@Component
public class Person {
	@Value("${name}")
    private String name;
    }

注意使用@PropertySource注解时,引入的是目标配置文件的全路径。在测试类中运行它:
在这里插入图片描述
可以看到,因为我只给person的name复制了,其他的属性应该为空,说明运行成功
同样,在配置文件中,我们还可以使用E-L表达式${}引入系统变量,比如使用随机数:
r a n d o m . i n t , 或 是 引 用 当 前 配 置 文 件 中 上 文 中 的 某 个 变 量 : {random.int},或是引用当前配置文件中上文中的某个变量: random.int{person.hello},直接看这个例子:

person:
 name: fengjian${random.int} # 使用随机数
 age: ${random.int}
 happy: false
 birth: 2021/7/17
 maps: {k1: v1,k2: v2}
 hello: happy
 list:
  - program
  - music
 dog:
  firstName: ${person.hello:hello}_旺财 #引用上文中person中的hello属性性,如果存在则使用该变量,如果不存在则显示hello
  age: 3

总结

这里拿yaml与properties进行比较,在上述两种赋值方式中可以发现,因为yaml可以存储对象而properties只能存储键值对,这就导致了在我们需要将多个值赋给实体类中时,properties需要一个个去赋值,而yaml只需一次绑定即可完成。
接下来用一张表归纳出两者的区别:

@ConfigurationProperties @Value
功能 批量注入配置文件中的属性 挨个指定
松散绑定(松散语法) 支持 不支持
SpEL 不支持 支持
JSR303数据校验 支持 不支持
复杂类型封装 支持 不支持

JSR-303数据校验

JSR是Java Specification Requests的缩写,意思是Java 规范提案。而JSR-303(Bean Validation 1.0 (JSR 303))是Java用于企业级开发中对Bean进行校验规范的技术。在上述的表中提到了,@ConfigurationProperties注解支持JSR-303数据校验,以及支持松散绑定,接下来将通过案例挨个介绍它们。

松散绑定

在类命名一个属性我们一般采用的是驼峰命名法,而在yml配置文件中,我们绑定类中对应的属性并不需要与之相同,比如类中的firstName,在yml中我们不仅可以写成first-name,还可以写成first_name,都是能够绑定成功的。

实体类:
SpringBoot配置文件_第6张图片
配置文件:
在这里插入图片描述

JSR-303

首先在实体类的上方使用@Validated注解开启校验,注意新版本的SpringBoot需要引入spring-boot-starter-validation依赖才可以使用它:
SpringBoot配置文件_第7张图片
以上面的实体类Person为例,假设想让name字段固定为电子邮件格式,只需在该属性上添加注解@Email:
在这里插入图片描述

注意看清楚,该注解是位于javax.Validation下的。该注解中有一个变量message,用于输出验证格式错误时的信息:
在这里插入图片描述

可以看到是有默认值的,我们也可以自己写一条信息:

@Email(message = "格式错误")
private String name;

绑定配置文件中的Person不变:
SpringBoot配置文件_第8张图片
在测试类中输出:
SpringBoot配置文件_第9张图片
发现报错了:
在这里插入图片描述
以上是JSR-303数据校验中的一个小例子,当然它能做的数据校验远远不止这些,下面列出一些常用的注解:

Constraint 详细信息
@Null 被注释的元素必须为 null
@NotNull 被注释的元素必须不为 null
@AssertTrue 被注释的元素必须为 true
@AssertFalse 被注释的元素必须为 false
@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值
@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值
@Size(max, min) 被注释的元素的大小必须在指定的范围内
@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内
@Past 被注释的元素必须是一个过去的日期
@Future 被注释的元素必须是一个将来的日期
@Pattern(value) 被注释的元素必须符合指定的正则表达式
@Email 被注释的元素必须是电子邮箱地址
@Length 被注释的字符串的大小必须在指定的范围内
@NotEmpty 被注释的字符串的必须非空
@Range 被注释的元素必须在合适的范围内

实际上这些注解都位于上面我提到的javax.Validation包中,而该包位于名为jakarta.validation-api.jar中:
SpringBoot配置文件_第10张图片

多配置文件

在实际开发过程中,我们在不同的环境中可能会用到不同的配置文件,如生产环境、测试环境以及项目上线后的运行环境等等。这时候我们就要用到多配置文件间的切换来达到切换环境的目的了。

再次又提到约定大于配置这句话了,SpringBoot中对多配置文件的名字默认识别格式是application-xxx.yml/properties。而默认读取的文件仍然是主配置文件application.yml/properties,而想要切换配置文件,只需在主配置文件中指定想要激活的配置文件即可

yaml多文档块

与properties文件不同,yml使用多配置文件时不仅可以生成多个配置文件,也可以像在java中,一个类文件中可以写多个类,实现在一个配置文件中完成多个配置文件的效果。使用 — 进行分割,就代表多个配置文件了:

server:
  port: 8081
spring:
  profiles:
    active: dev #指定激活的配置文件
---
server:
  port: 8082
spring:
  profiles: dev

---
server:
  port: 8083
spring:
  profiles: test
---

使用这种写法,相当于在项目根路径下存在两个名为application-dev和-test的配置文件。而使用spring-profiles-active就可以指定需要激活的配置文件,此处我指定的是dev配置文件生效,项目启动时如果跑着8082端口说明配置生效了:
在这里插入图片描述
值得注意的是,如果.properties和.yml文件都存在的情况下,会先读取properties中的配置项。并且多两者会将其中的配置项进行互补

配置文件读取优先级

官方文档中给出了我们可以放置配置文件的4个位置,他们是存在优先级的:

项目路径下的config文件夹配置文件>项目路径下配置文件>资源路径(classpath)下的config文件夹配置文件>资源路径(classpath)下配置文件

若多个位置上都存在配置文件,它们会按照优先级读取,且和上面yml和properties文件规则一样,如果每个配置文件中的配置项都不一样,也会进行互补。

配置文件与自动装配

在配置文件中我们编写一些配置,IDEA会给我们弹出提示:
SpringBoot配置文件_第11张图片
上一篇文章中简单的说了下自动装配,在这一章通过配置文件将自动装配联系起来再次理解一下。

上一章有说到,自动装配的关键在于启动类中的@EnableAutoConfiguration注解,该注解中导入了AutoConfigurationImportSelector类,该类会扫描带有spring.factories文件的jar,而spring.factories中以键值对的方式记录了类的url,会进行自动装配的类位于EnableAutoConfiguration键值对中,
由于它们都被@Configuration注解修饰,当它们被扫描后会以组件的形式被注入Spring容器,供我们使用。

也就是说,在EnableAutoConfiguration中存在的url才会被自动装配,那么接下来我们在EnableAutoConfiguration任取几个类,看看他们的结构:
在这里插入图片描述
这里就随便取了,分别点进去看看:
SpringBoot配置文件_第12张图片
SpringBoot配置文件_第13张图片
SpringBoot配置文件_第14张图片
不难看出,这三个类中都用到了许多相同的注解,这里主要说几个。
首先是@Configuration,这个不用多说,就是将当前类以组件的形式加入到Spring容器中。
其次是@EnableConfigurationProperties,它的功能从名字就不难看出,是将当前类启动配置文件Properties功能,而这是什么功能,在后面的括号中就能看出,应该是将该类与括号中的类相绑定,比如我们点进图三的CacheProperties类中:
SpringBoot配置文件_第15张图片
到这里应该就很熟悉了,在上面我们将实体类与配置文件的类相绑定时,使用的就是这种方式,这也就解释了为什么我们在配置文件中写配置时会弹出提示。而也能得出结论,配置项也不是我们随便能写的,是需要有相关的配置类才能够配置的。这又是一次约定大于配置的体现

最后是以@Conditional开头的注解,他们其实是属于一类用于断言的注解,当括号中的条件成立时,该类才会生效。也就是当满足一定条件的情况下,当前的类才会被自动装配起来。

总结

以下xxxProperties我将他们称为配置类,xxxAutoConfiguration称为自动装配类

  1. 自动装配类会与自动配置类相关联,但有一些类因为被断言注解修饰,需要满足括号中的条件才会生效,也就是被自动装配
  2. 配置文件中的各个配置项实际上是对应名为xxxProperties的配置类,因为该类被@ConfigurationProperties注解修饰,因此可以通过配置文件中的配置项与其绑定,完成参数配置
    3.能配置什么属性取决于该配置类中有哪些属性,并不是我们随意去写的

你可能感兴趣的:(SpringBoot)