【Spring Boot入门(6)】:SpringBoot-yaml配置文件介绍及应用

436 阅读11分钟

SpringBoot配置文件

1、配置文件类型

1.1、properties

这是我们熟悉的properties文件,同以前的properties用法

1.2、yaml

1.2.1、yaml简介

YAML 是 "YAML Ain't Markup Language"(YAML 不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:"Yet Another Markup Language"(仍是一种标记语言)。比XML更省资源,方便,非常适合用来做以数据为中心的配置文件

1.2.2、基本语法

  • key: value;kv之间有空格
  • key和value的值是区分大小写的
  • 使用缩进表示层级关系,xml文件中是用一个标签的开闭表示一个级别,标签内部的开闭标签就是父子关系
  • 缩进不允许使用tab,只允许使用空格
  • 缩进的空格数不重要,只要相同层级的元素左对齐即可,所以,但是在idea中使用tab也没关系,对的齐就行
  • #表示注释
  • 字符串无需加引号,如果要加,''与""表示字符串内容 会被转义/不转义
  • 当我们使用单引号和双引号来修饰value的值时,如果value中有\n这种在Java语言中表示转义的字符时:
    • 双引号修饰的话,输出到控制台的value值,\是发挥转义的作用的,就是会换行
    • 单引号修饰的话,输出到控制台的value值,\是不发挥转义的作用的,会把\n输出来

1.2.3、数据类型

字面量:单个的、不可再分的值。date、boolean、string、number、null

#k: V 有空格

k1: v1
k2: v2
k3: v3

对象:键值对的集合。map、hash、set、object

#对象中是有属性的,这个对象中的属性在同一级,所以要对齐。但是属性如果也是个对象,属性的属性就是下一级
#行内写法:
k: {k1: v1,k2: v2,k3: v3}
#或这样,这样写k:的后面是可以不用加空格的
k:
  k1: v1
  k2: v2

数组:一组按次序排列的值。array、list、queue

#行内写法:
k: [v1,v2,v3]
#或这样,-表示k,k有多个值,就是数组。-后面要有空格然后加v,注意没有:
k:
- v1
- v2
- v3

1.2.4、使用yaml文件封装成javaBean

前面使用了properties 文件来演示JavaBean的封装,这次使用yaml格式的文件来演示

创建一个Person类,如下。然后进行配置绑定,创建一个application.yaml文件在resources目录下,它和application.properties文件是可以共存的,但是application.properties配置的优先级是大于yaml的,properties里面的配置会覆盖yml里面的配置

@ConfigurationProperties(prefix = "person")//和配置文件中前缀为person的进行绑定
@Component//让容器创建这个组件
@Data
@ToString
public class Person {
    private String name;
    private Integer age;
    private Boolean happy;
    private Date birth;
    private Map<String,Object> maps;
    private List<Object> lists;
    private Dog dog;
}

创建一个Dog类

@Data
@Component //被容器托管
public class Dog {
    private String name;
    private String age;
}

使用properties

用properties文件表示以上对象这么用,比如,类上先加上条件注解

@ConfigurationProperties(prefix = "person")//和配置文件中前缀为person的进行绑定
@Component//让容器创建这个组件
@Data
public class Person {

再在配置文件里面修改[配置类中属性],他只能添加键值对。

person.username=xxx

使用yaml

yaml[yml]文件表示以上对象:source下新建【yml优先级小于properties】,可以直接给实体类赋值

person:
  name: qinjiang1
  age: 3
  happy: false
  birth:  2019/3/26
  maps: {k1: v1,k2: v2}
  lists:
    - code
    - girl
    - music
  dog:
    name: 旺财
    age: 3


测试:在Controller类中写一个接口,返回Person对象,测试接口

@Slf4j
@RestControlLer
public class HelloController {
    @Autowired
    Person person;
    @RequestMapping("/person" )
    public Person person(){
        log.warn("提示:开始进行请求处理");
        return person;
    }
}

启动主程序:访问:localhost:8080/person

image.png

还有,我们的类和配置文件直接关联着 , 我们使用的是@configurationProperties的方式,我们还讲道过方式2:@EnableConfigurationProperties + @ConfigurationProperties注解,这种方式不产生参考第3节。除此之外,还有一种方式是使用@value

Person类

@ConfigurationProperties(prefix = "person")//和配置文件中前缀为person的进行绑定
@Component//让容器创建这个组件
@Data
public class Person {
    @Value("${person.name}")//从配置文件中取值
    private String name;
    @Value("#{1*2}")//#{SPEL}   spring表达式
    private Integer age;
    @Value("true")//字面量
    private Boolean happy;
    private Date birth;
    private Map<String,Object> maps;
    private List<Object> lists;
    private Dog dog;
}

Dog类

@Data
@Component //被容器托管
public class Dog {
    @Value("旺财1")
    private String name;
    @Value("3*")
    private String age;
}

测试:

Dog(name=旺财1, age=3*)

2、配置提示

我们发现我们在yaml文件时,即使用@ConfigurationProperties注解将javabean和属性资源配置文件绑定了,在编写标签值时,却没有提示,所以我们要解决这个问题。而且我们的Person类上面也一直提示我们没有配置注释处理器

自定义的类和配置文件绑定一般没有提示。引入配置处理器

注意:2.4.2版本修改了文档,不需要加了,但是默认会把lombok添加到exclude中

<!--注释处理器-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <!--配置maven打包插件打包时忽略注释处理器的jar包-->
            <configuration>
                <excludes>
                    <exclude>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-configuration-processor</artifactId>
                    </exclude>
                </excludes>
            </configuration>
        </plugin>
    </plugins>
</build>

3、加载指定配置文件(@PropertySource)

@PropertySource :加载指定的配置文件;使用@configurationProperties默认从全局配置文件中获取值;

resource目录下新建一个lemon.properties,在其内部进行写值

name = lemon

Person类

//@ConfigurationProperties(prefix = "person")//和配置文件中前缀为person的进行绑定
@PropertySource(value = "classpath:lemon.properties")
@Component//让容器创建这个组件
@Data
public class Person {
    @Value("${name}")//从配置文件中取值
    private String name;
    @Value("#{1*2}")//#{SPEL}   spring表达式
    private Integer age;
    @Value("true")//字面量
    private Boolean happy;
    private Date birth;
    private Map<String,Object> maps;
    private List<Object> lists;
    private Dog dog;
}

运行结果:

image.png

4、配置文件占位符

随机数

${random.value}、${random.int}、${random.long}、${random.int(10)}

占位符引用其他属性的值,如果不存在可以设置默认值,编写yml配置文件,

person:
    name: qinjiang${random.uuid}
    age: ${random.int}
    happy: false
    birth: 2000/01/01
    maps: {k1: v1,k2: v2}
    lists:
      - code
      - girl
      - music
    dog:
      name: ${person.hello:hello}_旺财
      age: 1

这个使用起来并不友好!我们需要为每个属性单独注解赋值,比较麻烦;

image.png

cp只需要写一次即可 , value则需要每个字段都添加

松散绑定 :这个什么意思呢? 比如我的yml中写的last-name,这个和lastName是一样的,-后面跟着的字母默认是大写的。这就是松散绑定

JSR303数据校验 , 这个就是我们可以在字段是增加一层过滤器验证 , 可以保证数据的合法性

复杂类型封装,yml中可以封装对象 , 使用@value就不支持

结论:

  • 配置yml和配置properties都可以获取到值 , 强烈推荐 yml
  • 如果我们在某个业务中,只需要获取配置文件中的某个值,可以使用一下 @value
  • 如果说,我们专门编写了一个JavaBean来和配置文件进行映射,就直接使用@configurationProperties不要犹豫!

5、JSR303数据校验

jsr303就是在属性字段上增加一层过滤器验证,可以保证数据的合法性。

使用方式:在需要属性赋值的类上添加一个@Validated注解,然后在需要验证的属性上添加各种不同的验证注解来约束这个字段应该填什么或是应该填什么格式。spring-boot中可以用@validated来校验数据,如果数据异常则会统一抛出异常,方便异常中心统一处理。我们这里来写个注解让我们的name只能支持Email格式

步骤:

导入spring-boot-starter-validation依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

Person类

@ConfigurationProperties(prefix = "person")//和配置文件中前缀为person的进行绑定
//@PropertySource(value = "classpath:lemon.properties")
@Component//让容器创建这个组件
@Data
@Validated  //数据校验
public class Person {
    @Email(message = "邮箱格式错误") //name必须是邮箱格式
    private String name;
    @Value("#{1*2}")//#{SPEL}   spring表达式
    private Integer age;
    @Value("true")//字面量
    private Boolean happy;
    private Date birth;
    private Map<String,Object> maps;
    private List<Object> lists;
    private Dog dog;
}

启动类

@SpringBootApplication
public class MainApplication {
    public static void main(String[] args) {
        //1.返回我们IOC容器
        SpringApplication.run(MainApplication.class, args);
​
    }
}

application.yaml

person:
  name: 1234567@123.com  #输入非邮箱格式则报异常
  age: 3
  happy: false
  birth:  2019/3/26
  maps: {k1: v1,k2: v2}
  lists:
    - code
    - girl
    - music
  dog:
    name: 旺财
    age: 3

控制器:

@RequestMapping("/person")
public Person person(){
    return person;
}

测试:正确和错误的输入方式

image.png

总结

使用数据校验,可以保证数据的正确性; 还有很多这样的校验注解,具体如下

//空检查 
@Null 验证对象是否为null 
@NotNull 验证对象是否不为null, 无法查检长度为0的字符串 
@NotBlank 检查约束字符串是不是Null还有被Trim的长度是否大于0,只对字符串,且会去掉前后空格. 
@NotEmpty 检查约束元素是否为NULL或者是EMPTY.
​
//Booelan检查 
@AssertTrue 验证 Boolean 对象是否为 true 
@AssertFalse 验证 Boolean 对象是否为 false//长度检查 
@Size(min=, max=) 验证对象(Array,Collection,Map,String)长度是否在给定的范围之内 
@Length(min=, max=) Validates that the annotated string is between min and max included.
​
//日期检查 
@Past 验证 Date 和 Calendar 对象是否在当前时间之前,验证成立的话被注释的元素一定是一个过去的日期 
@Future 验证 Date 和 Calendar 对象是否在当前时间之后 ,验证成立的话被注释的元素一定是一个将来的日期 
@Pattern 验证 String 对象是否符合正则表达式的规则,被注释的元素符合制定的正则表达式,regexp:正则表达式 flags: 指定 Pattern.Flag 的数组,表示正则表达式的相关选项。
​
//数值检查 
建议使用在Stirng,Integer类型,不建议使用在int类型上,因为表单值为“”时无法转换为int,但可以转换为Stirng为”“,Integer为null 
@Min 验证 Number 和 String 对象是否大等于指定的值 
@Max 验证 Number 和 String 对象是否小等于指定的值 
​
@DecimalMax 被标注的值必须不大于约束中指定的最大值. 这个约束的参数是一个通过BigDecimal定义的最大值的字符串表示.小数存在精度 
​
@DecimalMin 被标注的值必须不小于约束中指定的最小值. 这个约束的参数是一个通过BigDecimal定义的最小值的字符串表示.小数存在精度 
​
@Digits 验证 Number 和 String 的构成是否合法 
​
@Digits(integer=,fraction=) 验证字符串是否是符合指定格式的数字,interger指定整数精度,fraction指定小数精度。 
​
@Range(min=, max=) 被指定的元素必须在合适的范围内
​
@Range(min=10000,max=50000,message=”range.bean.wage”) 
    
@Valid 递归的对关联对象进行校验, 如果关联对象是个集合或者数组,那么对其中的元素进行递归校验,如果是一个map,则对其中的值部分进行校验.(是否进行递归验证) 
    
@CreditCardNumber信用卡验证 
@Email 验证是否是邮件地址,如果为null,不进行验证,算通过验证。 
@ScriptAssert(lang= ,script=, alias=) 
@URL(protocol=,host=, port=,regexp=, flags=)

6、配置文件读取位置

根据官方文档可知,springboot会从下面四个路径读取配置文件

  • file:./config/ :表示可以读取项目路径下根路径的config目录中的配置文件
  • file:./ :表示可以读取项目路径下根路径的配置文件
  • classpath:/config :表示可以读取类路径下根路径的config目录中的配置文件
  • classpath:/ :表示可以读取类路径下根路径的配置文件

优先级按照上面的排序自上而下降低

  • 其中file指的是项目路径或者说该模块路径:即下图c-springboot-config这个模块的路径
  • classpath指的就是类路径:就是java目录或者resource目录下(一般我们是放在resource目录中),编译后生成的target目录中存储的就是这两个目录中的东西

我们在该模块的四个位置添加yaml配置文件,测试那个点优先级高

image.png

7、指定位置加载配置文件

我们还可以通过spring.config.location来改变默认的配置文件位置,项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置;

java -jar spring-boot-config.jar --spring.config.location=F:/application.properties

这种情况,一般是后期运维做的多,相同配置,外部指定的配置文件优先级最高

外部加载配置文件的方式十分多,我们选择最常用的即可,在开发的资源文件中进行配置!

8、多环境配置文件的选择

有时候我们在开发时,我们需要在不同环境下进行切换开发,比如测试环境、生产环境等,在不同环境真好切换,就需要读取不同的配置文件来进行开发调试。具体实现如下

第一种:properties类型配置文件的多配置文件模式

我们在resource目录在现有application.properties配置文件的前提下新增两个环境的配置文件:

  • application-dev.properties:表示的是开发环境使用的
  • application-test.properties:表示的是测试环境下使用的

但是Springboot并不会直接启动这些配置文件,它默认使用application.properties主配置文件;我们需要通过一个配置来选择需要激活的环境;

#比如在配置文件中指定使用dev环境,我们可以通过设置不同的端口号进行测试;
#我们启动SpringBoot,就可以看到已经切换到dev下的配置了;
spring.profiles.active=dev

方式二:yml的多文档块

和properties配置文件中一样,但是使用yml去实现不需要创建多个配置文件,更加方便了,第一种方式需要写的配置文件很多,环境较多的时候不方便,一般我们使用第二种

只需要在yaml文件中写多个文档模块进行区分就好了,使用---来进行一个yaml文件中不同的模块,但不推荐

server:
  port: 8081
#选择要激活那个环境块
spring:
  profiles:
    active: prod
---
server:
  port: 8083
#配置环境的名称
spring:
  profiles: dev

---

server:
  port: 8084
spring:
  profiles: prod  #配置环境的名称

注意:如果yml和properties同时都配置了端口,并且没有激活其他环境 , 默认会使用properties配置文件的!