SpringBoot③YAML和JSR-303

4、YAML

4.1、SpringBoot配置文件

为什么需要配置文件

  • Spring Boot 默认实现了很多自动配置。
  • 当我们不想用默认配置时,可以通过配置文件来自定义配置。
  • 约定大于配置:开发人员仅需规定不符合规定的部分,没有规定配置的地方采用默认配置,以达到最简配置。

Spring Boot 配置文件

Spring Boot 使用全局的配置文件,文件名称为application(这个名称是固定的)。

  • application.properties

    • 语法Key=Value

    • 例如

      server.port=8081
      
  • application.yaml(官方建议使用.yaml扩展名,尽量不要用.yml扩展名)

    • 语法Key:空格Value

    • 例如

      server
       port: 8081
      

4.2、YAML

👉JSON & YAML

4.3、注入YAML配置文件

4.3.1、Spring注入

学习 YAML 配置注入之前,先思考一下 Spring 常用的三种注入方式

环境搭建

基于注解的自动注入进行测试。

  1. 在主程序的同级目录下,新建 pojo 包;

  2. 在包中新建一个 pet 类,使用@Value注入属性值:

    @Component
    public class Pet {
    
        @Value("小七")
        private String name;
    
        @Value("3")
        private Integer age;
    
        @Override
        public String toString() {
            return "Pet{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    

测试

@SpringBootTest
public class PetTest {
    /**
     * 自动注入pet
     */
    @Autowired
    Pet pet;

    @Test
    public void test() {
        System.out.println(pet);
    }
}

下面编写一个复杂的实体类,来对 YAML 配置注入进行测试。

4.3.2、YAML注入

  • 编写application.yaml配置文件,使用@ConfigurationProperties引入
  • 通过 setter 方式自动注入,要求实体类具有 setter

环境搭建

编写一个复杂的实体类,测试 YAML 注入属性

  1. pojo 包中创建 Person

    @Component
    public class Person {
        private String name;
        private Integer age;
        private Boolean gender;
        private Date birthday;
        private List<String> list;
        private Map<String, Object> map;
        private Pet pet;
        
        // 每个属性的setter
        
        @Override
        public String toString() {
            return "Person{" + "\n" +
                    " name='" + name + '\'' + "\n" +
                    " age=" + age + "\n" +
                    " gender=" + gender + "\n" +
                    " birthday=" + birthday + "\n" +
                    " list=" + list + "\n" +
                    " map=" + map + "\n" +
                    " pet=" + pet + "\n" +
                    '}';
        }
    }
    
  2. 编写 YAML 配置文件application.yaml

    • 配置与实体类的属性一一对应;
    • 注意空格
    person:
      name: jaywee
      age: 7
      gender: true
      birthday: 2007
      list:
        - java
        - spring
      map:
        k1: v1
        k2: v2
      pet:
        name: 小七
        age: 3
    
  3. Person 类中引入 YAML 配置文件

    • 使用注解@ConfigurationProperties(prefix="xx")

    • prefix 的值与 YAML 文件中最左边的配置对应

      @ConfigurationProperties(prefix = "person")
      @Component
      public class Person {
          ...
      }
      

测试

  1. 输出的属性为 null,可能是以下原因:
    • 实体类的属性名和 YAML 文件不一致;
    • 实体类没有 setter 方法;
  2. 报错Failed to convert from type [java.lang.String] to type [java.util.Date] for value 'xxx'
    • 原因YAML 文件的日期格式错误,必须是xxxx/xx/xx格式
@SpringBootTest
public class PersonTest {
    /**
     * 自动注入person
     */
    @Autowired
    Person person;

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

关于 Spring Boot Configuration Annotation Processor 的说明

  • 部署 Spring Boot 配置文件时,IntelliJ IDEA 会报红:

    • Spring Boot Configuration Annotation Processor not configuredSpring Boot 配置注解处理器没有配置)
    • 不影响运行
  • Spring Boot 配置注解处理器

    • 导入依赖

      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-configuration-processor</artifactId>
          <optional>true</optional>
      </dependency>
      
    • 配置该处理器之后,实体类的字段与 YAML 配置之间有可视化的映射关系;

4.3.3、指定配置文件注入

  • 自定义.properties配置文件,使用@PropertiesSource引入
  • 使用@Value(${xxx})注入

测试

person 类的部分属性注入进行测试

  1. resources 目录下编写配置文件

    name=SecretMrJ
    age=7
    gender=true
    
  2. Person 类中引入配置文件

    @PropertySource("classpath:jaywee.properties")
    @Component
    public class Person {
    
        @Value("${name}")
        private String name;
    
        @Value("${age}")
        private Integer age;
    
        @Value("${gender}")
        private Boolean gender;
    
        ...
    }
    
  3. 测试:注入成功

4.3.4、小结

常用注入方式

Spring 阶段

  1. 构造器注入、setter 注入:在 Spring 中常用,通过 XML 配置实现;
  2. 基于注解的自动注入:使用 @Value 等注解进行注入;

Spring Boot 阶段

  1. YAML 注入Spring 官方推荐,通过 @ConfigurationProperties 引入配置文件!
  2. 指定配置文件注入:通过 @PropertySource 引入配置文件,使用 @Value 注解。

YAML 注入 vs 指定配置文件注入

YAML注入 指定配置文件注入
配置文件 application.yaml 自定义配置文件
引入方式 @ConfigurationProperties
默认从全局配置文件中获取值
@PropertiesSource
加载指定的配置文件
注入方式 自动将属性批量注入 @Value 为每个属性注入
功能支持 松散绑定、JSR303 数据校验、复杂类型封装 SpEL

功能说明

功能 说明
松散绑定 属性的驼峰式下划线短横线,不同命名方式之间可以绑定。
如:first_name 可以与 firstName 对应并绑定。
JSR303 数据校验 在属性上增加一层过滤器验证,保证数据的合法性
复杂类型封装 YAML 文件中支持封装对象
SpEL Spring Expression LanguageSpring 表达式语言),比 JSPEL 表达式更强大

结论

一般情况下推荐使用 YAML

  • 只需要获取配置文件中的某个值,使用@Value
  • 需要批量获取配置文件中的值,使用@ConfigurationProperties注入 YAML 配置文件
    • 如:编写 JavaBean 与配置文件一一映射。

4.4、拓展:JSR303数据校验

JSRJava Specification Requests):Java 规范提案

  • 指的是向 JCPJava Community Process)提出新增一个标准化技术规范的正式请求;
  • 任何人都可以提交 JSR,以向 Java 平台增添新的 API 和服务;
  • JSR 已成为 Java 界的一个重要标准。

JSR-303JAVA EE 6 中的一项子规范,叫做Bean Validation

  • Spring Boot 中,可以使用注解 @Validated 来校验数据;

  • 如果数据异常则会统一抛出,方便异常的中心统一处理;

  • 使用方式

    1. 导入 starter 依赖

      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-validation</artifactId>
      </dependency>
      
    2. 在类上方:使用注解 @Validated

    3. 在属性上方:使用相应功能的注解

下面搭建一个环境,来对 JSR-303 进行测试。

4.4.1、创建 Employee

创建 Employee 类,使用 JSR

@Component
@ConfigurationProperties(prefix = "employee")
@Validated
public class Employee {
    @NotNull
    private String name;
    @Max(100)
    private int age;
    @Email
    private String email;

	// setter、toString()
}

4.4.2、编写 YAML 配置

employee:
  name: jaywee
  age: 7
  email: jaywee7@126.com

4.4.3、测试

测试类

@SpringBootTest
public class EmployeeTest {

    @Autowired
    private Employee employee;

    @Test
    void test() {
        System.out.println(employee);
    }
}

测试结果

进一步测试

  1. 修改 YAML 配置进行测试,查看报错结果
    • 去掉 name(此时 name 为空)
      • codes [employee.name,name]; arguments []; default message [name]]; default message [不能为null]
    • age 改为101(此时 age 超过最大值100)
      • codes [employee.age,age]; arguments []; default message [age],100]; default message [最大不能超过100]
    • 邮箱改为 jaywee777(此时 email 不是邮箱格式)
      • default message [不是一个合法的电子邮件地址]
posted @ 2021-09-10 23:59  Jaywee  阅读(46)  评论(0编辑  收藏  举报

👇