Spring 全家桶之 Spring Boot 2.6.4(二)- Configuration(Part A)

2022-08-24 14:34:37 浏览数 (1)

一、Spring Boot 配置文件

  Spring Boot使用一个全局配置文件application.properties,也可以使用yml格式,配置文件默认放在在resources目录下,代码中指定配置文件时指定的方式为”classpath:application.properties“。使用IDEA创建Spring Boot项目默认的配置文件是properties格式。

Spring Boot的全局配置文件可以对默认配置进行修改。

二、YMAL 配置文件

新建项目spring-boot-configuration,导入基本的Web依赖及Lombok依赖,将application.properties配置文件改为application.yml;并新建entity包,增加Person和Dog实体类

代码语言:javascript复制
@Data
public class Person {
    private String lastName;
    private Integer age;
    private Boolean boss;
    private Date birth;

    private Map<String,Object> maps;
    private List<Object> list;
    private Dog dog;
}
代码语言:javascript复制
@Data
public class Dog {
    private String name;
    private Integer age;
}

2.1 - YAML配置文件基本语法

YAML基本语法

YAML基本语法规则如下:

  • 使用缩进表示层级关系
  • 缩进时不允许使用Tab键,只允许使用空格
  • 缩进的空格数量不重要,只要相同层级的元素左侧对其即可
  • 大小写敏感

YAML支持的数据结构有:

  • 对象:键值对的集合
  • 数组:一组按次序排列的值
  • 字面量:单个的、不可分割的值

YAML的格式是k: v格式, 表示一对键值对(冒号后面必须有空格),以空格的缩进来控制层级关系,只要是做对齐的一列数据,都认为是同一层级。如yml中对应用访问端口的配置

代码语言:javascript复制
server: 
    port: 8081
    path: /

这里就是通过缩进来表示层级关系,path和port为同一层级,yml文件中属性和值是大小写敏感的。

YAML配置文件中支持的数据类型

字面量:既普通值,包括数字、字符串、布尔值(true和false) 格式为key: value格式, 字面值直接写,字符串默认不用加上单引号或者双引号。 单引号和双引号在yml配置文件中是有区别的

  • ”“:双引号不会转义特殊字符,特殊字符会作为本身想表示的作用,
    • 如name: "zhangsannlisi", 输出 张三 换行 lisi
  • ‘’: 单引号会转义字符串,特殊字符串最终只是一个普通的字符串数据
    • 如name: 'zhangsan n lisi', 输出 zhangsan n lisi

对象及Map(属性和值/键值对) 格式为key: value,在对象名称的下一行以k: v的形式写上属性名和value 对象具体属性名和属性值的书写格式还是还是k: v格式

代码语言:javascript复制
friend: # 对象名
    # 对象包含的属性名和属性值
    lastName: zhangsan # 属性名: 属性值
    age: 30

另外一种写法是行内写法,既使用{}来包括属性名和属性值的k: v。

代码语言:javascript复制
friend:{lastName: zhangsan, age: 18}

数组(List,Set),用 -value 表示数组中的一个元素

代码语言:javascript复制
# 数组或者集合名
pets: 
    # 集合中包含的元素
    - cat
    - dog
    - pig

也可以使用[],value之间使用“,”隔开

代码语言:javascript复制
pets: [cat,dog,pig]

复合结构,既包含了对象、数组、字符串等各种形式的数据

使用YML配置文件给Person对象属性赋值

将resources目录下的application.properties重命名为application.yml,使用yml来给Person对象赋值,并导入配置文件处理依赖,书写配置文件时IDEA会有提示

代码语言:javascript复制
<!--导入配置文件处理器-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

application.yml配置文件内容为

代码语言:javascript复制
# 对象名
person:
  # 属性名: 属性值
  lastN-name: stark
  age: 40
  boss: true
  birth: 1970/12/12
  maps: {k1: v1, k2: v2}
  list:
    - l1
    - l2
    - l3
    - l4
  dog:
    name: pipi
    age: 2

将YML配置文件中的属性值映射的Person对象中需要使用到@ConfigurationProperties注解,这个注解将标注类和注解中指定的配置进行绑定(默认指定的配置文件是application.yml), 注解中prefix属性表示配置的前缀,将这个前缀下的配置与Person对象中的属性进行一一映射

还需要使用@Component注解将该类加入到Spring容器中,并且必须是容器中组件才能使用@ConfigurationProperties注解,从容器中获取Person对象并输出,查看是否赋值成功

在Person实体类上增加注解

代码语言:javascript复制
@ConfigurationProperties(prefix = "person")
@Component
@Data
public class Person {
    // 中间内容不变
}

在test包下新增测试类PersonTest

代码语言:javascript复制
@SpringBootTest
public class PersonTest {

    @Autowired
    private Person person;

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

}

执行测试

控制台输出Person对象,属性被成功赋值

利用properties文件配置给对象赋值

代码语言:javascript复制
person.last-name=stark1
person.age=19
person.birth=1980/12/12
person.boss=true
person.maps.k1=v1
person.maps.k2=v2
person.list=a,b,c
person.dog.name=pipi
person.dog.age=2

注释yml文件中的配置,执行测试

同样可以成功给Person的属性赋值。

当yml和properties两种格式的配置文件同时存在时yml格式优先级更高

使用@Value注解给属性赋值

除了@ConfigurationProperties注解来指定配置前缀进行赋值,还可以使用@Value注解来指定配置和属性一一绑定。@Value注解的作用与Spring XML配置文件中bean标签下的property的value属性的作用是一致的,主要用来给属性赋值。

在Person中实体类属性上使用@Value注解

代码语言:javascript复制
//@ConfigurationProperties(prefix = "person")
@Component
@Data
public class Person {
    @Value("${person.last-name}")
    private String lastName;
    @Value("#{10*2}")
    private Integer age;
    @Value("true")
    private Boolean boss;
    // 其余内容不变
}

修改application.yml中配置文件内容为

代码语言:javascript复制
person:
  last-name: stark

执行PersonTest测试

同样可以将Person实体类的lastName属性与配置文件中的配置绑定成功,根据输出@Value还支持一些表达式。

@Value只支持取出基本类型数据,在Person实体类的maps属性上使用@Value注解来获取配置文件中的数据

代码语言:javascript复制
@Value("${person.maps}")
private Map<String,Object> maps;

修改application.yml配置文件

代码语言:javascript复制
  # ....
  maps: {k1: v1, k2: v2}
  list:
    - l1
    - l2
    - l3
    - l4
  dog:
    name: pipi
    age: 2

执行测试

Person对象的maps属性赋值失败。

@Value&emsp; VS &emsp;@ConfigurationProperties

&emsp;&emsp;&emsp;

@ConfigurationProperties &emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;

@Value&emsp;&emsp;&emsp;&emsp;&emsp;

功能 &emsp;&emsp;

批量注入配置文件中的属性值 &emsp;

逐个指定属性所对应的值 &emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;

松散绑定语法

支持

不支持

SpEL表达式

不支持

支持

JSR303数据校验

支持

不支持

复杂类型封装

支持

不支持

松散绑定不支持测试
代码语言:javascript复制
person:
  last-name: stark
代码语言:javascript复制
@Value("${person.lastName}")
private String lastName;

执行测试 @Value("

plus:属性名匹配规则,以Person实体类的lastName属性为例,在配置文件中可以写成以下几种形式

  • person.lastName:与属性名一致
  • person.last-name:使用 - 连接,并将大写改为小写
  • person.last_name:使用 _ 连接,并将首字母大写改为小写
数据校验不支持测试

Spring Boot 在2.3 版本之后 Web Staters中不再包含validation,查看官方文档Validation Starter no longer included in web starters,如果需要使用validation,导入以下依赖

代码语言:javascript复制
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

在Person实体类的lastName属性上增加@Email注解,校验是否为合法的email地址

代码语言:javascript复制
//@ConfigurationProperties(prefix = "person")
//@PropertySource(value = {"classpath:person.properties"})
@Component
@Data
@Validated
public class Person {

    @Email
    @Value("${person.last-name}")
    private String lastName;
    // 其余内容不变
}    

控制台成功输出person对象,说明@Email注解并未生效

代码语言:javascript复制
@ConfigurationProperties(prefix = "person")
//@PropertySource(value = {"classpath:person.properties"})
@Component
@Data
@Validated
public class Person {

    @Email
    // @Value("${person.last-name}")
    private String lastName;
    // 其余内容不变
}    

再次执行PersonTest

控制台输出“不是一个合法的电子邮件地址”,成功执行了校验

@Value与@ConfigurationProperties如何选择?

如果只是在业务逻辑中获取配置文件中某一项配置的值,建议使用@Value,如果有一个实体类和配置文件进行映射时建议使用@ConfigurationProperties

使用@Value注解的简单例子

增加HelloController

代码语言:javascript复制
@RestController
public class HelloController {

    @Value("${person.last-name}")
    private String name;

    @RequestMapping("/hi")
    public String hi(){
        return "Hi, "   name;
    }
}

重启启动应用

0 人点赞