SpringBoot - yml配置文件

SpringBoot使用一个全局配置文件,配置文件名固定:

  • application.properties
  • application.yml

application.properties端口设置8081,application.yml端口设置8082,运行启动类,优先走8081。

两个配置文件互补,application.properties优先级 > application.yml优先级。

目录

配置文件格式

配置文件值注入

[1. 注入值](#1. 注入值)

[2. 松散绑定](#2. 松散绑定)

[3. SpEL](#3. SpEL)

[4. JSR303 数据校验](#4. JSR303 数据校验)

[5. 复杂类型封装](#5. 复杂类型封装)

@PropertySource&@ImportResource&@Bean

@PropertySource

@ImportResource

@Bean

配置文件占位符

多Profile文件

在配置文件中指定运行环境

​编辑

在外部指定运行环境

配置文件加载位置

外部配置加载顺序


配置文件格式

YML配置格式:

  1. k:(空格)v:表示一对键值对(空格必须有);

    1. 字符串默认不用加上单引号或者双引号;
    2. "":双引号;不会转义字符串里面的特殊字符;特殊字符会作为本身想表示的意思(例子:name: "zhangsan \n lisi":输出;zhangsan 换行 lisi)
    3. '':单引号;会转义特殊字符,特殊字符最终只是一个普通的字符串数据(例子:name: 'zhangsan \n lisi':输出;zhangsan \n lisi)
  2. 以空格的缩进来控制层级关系;只要是左对齐的一列数据,都是同一个层级的;

  3. 属性和值也是大小写敏感;

    server:
    port: 8085

properties配置格式:

复制代码
server.port=8084

配置文件值注入

配置文件中,无论是yml还是properties他们都能获取到值。

在实体类上使用 @ConfigurationProperties 进行值注入。

  1. @ConfigurationProperties: 告诉SpringBoot将本类中的所有属性和配置文件中相关配置进行绑定,默认从全局配置文件中获取值。
  2. prefix = "person": 配置文件中哪个与本类中的属性进行一一映射

1. 注入值

前期准备:

  1. 创建实体类

    1. person类:(简单属性)id、name、personname、address、boss、birth、
      (复杂类型)lsit类型、map类型、dog对象、dog对象列表

    2. dog类:id、name

      java 复制代码
      public class Person {
      
          private Integer id;
          private String name;
          private String address;
          private Boolean boss;
          private Date birth;
      
          private String personName;
          private List<String> hobby;
          private Map<String,Object> maps;
          private Dog dog;  // 嵌套对象
          private List<Dog> dogs; // dog对象列表
      
          // 提供无参构造、有参构造、Getter和setter对象,以及重新toString
      }
      
      
      public class Dog {
          private String name;
          private Integer age;
      
          // 提供无参构造、有参构造、Getter和setter对象,以及重新toString
      }
    3. 将实体类交由spring管理,在实体类上加上 @Component 注解

  2. 书写配置文件: 在application.yml配置文件中写person的属性值

    1. 简单属性

      java 复制代码
      person:
        # 普通属性
        id: 1
        name: "zhangsan \n lisi"
        address: 北京
        boss: true
        birth: 2025/1/18
    2. list集合

      java 复制代码
        # list集合书写
        # 方式一
        # lists: {篮球,足球}
      
        # 方式二
        lists:
          - 篮球
          - 足球
          - 乒乓球
    3. map集合

      java 复制代码
        # map集合书写
        maps: {sex: male,email: 123456789@qq.com}
    4. dog属性

      java 复制代码
        # dog属性
        dog:
          name: 小狗
          age: 2
    5. dog列表属性

      java 复制代码
        # dog对象list集合
        # 方式一:行内列表格式
      #  dogs:
      #    - name: 小黑
      #      age: 3
      #    - name: 小黄
      #      age: 2
      #    - {name: "金毛",age: 1}
      
        # 方式二:块式列表格式
        dogs:
          - name: 小黑
            age: 3
          - name: 小黄
            age: 2
          - name: 金毛
            age: 1
    6. 松散绑定

      java 复制代码
        # 松散绑定(下面的方式都可以实现)
      #  personName: wangwu
      #  person_name: wangwu
      #  person-name: wangwu
        PERSONNAME: wangwu
  3. 绑定值

    1. @Value: 需要对属性一个一个的进行注入,只能为简单属性进行注入,复杂类型不支持。 在使用@Value注解注入值时,并不强制要求属性提供setter方法。Spring框架可以通过反射直接设置字段的值,即使没有setter方法。

      但是,如果类中的属性是私有的,并且没有setter方法,Spring会通过反射来设置值。然而,在实际开发中,为了符合JavaBean的规范,以及方便其他代码(如序列化、其他框架使用)使用,通常我们会提供getter和setter方法。

      另外,需要注意的是,如果使用@Value注解在非Spring管理的类中,或者在没有Spring容器管理的环境下,那么注解将不会生效。因此,确保这个类是由Spring容器管理的(如使用@Component、@Service等注解,或者通过XML配置)。
      由于复杂类型没有注入值,值为null。

      java 复制代码
      //使用@Value注值
      @Component //交给spring管理
      public class Person {
      
          @Value("${person.id}")
          private Integer id;
          @Value("${person.name}")
          private String name;
          @Value("${person.address}")
          private String address;
          @Value("${person.boss}")
          private Boolean boss;
          @Value("${person.birth}")
          private Date birth;
      
          private String personName;
          private List<String> lists;
          private Map<String,Object> maps;
          private Dog dog;  // 嵌套对象
          private List<Dog> dogs;
      }
    2. @ConfigurationProperties: 可以批量给属性注值,且复杂类型也可以进行注值 使用 @ConfigurationProperties 注解进行属性绑定时,必须提供 setter 方法,因为 Spring 是通过调用 setter 方法来注入属性的。同样,如果需要访问这些属性,也需要 getter 方法。

      原因:

      @ConfigurationProperties 绑定属性时,使用的是 JavaBean 的规范,即通过 setter 方法设置值。如果没有 setter 方法,Spring 将无法将属性值设置到对应的字段上。

      但是,请注意:

      1. 如果使用 Lombok 的 @Data 注解,它会自动生成 getter 和 setter,这样就可以。

      2. 如果属性是 final 的,那么必须通过构造函数来注入,这时候就不能用 setter 了。
        但是 @ConfigurationProperties 默认要求有无参构造函数和 setter,所以对于 final 字段,我们需要提供构造函数,并且使用 @ConstructorBinding 注解(在 Spring Boot 2.2 以后引入)。

      java 复制代码
      //方式二:使用注解
      @Component //交给spring管理
      @ConfigurationProperties(prefix = "person")
      public class Person {
      
          private Integer id;
          private String name;
          private String address;
          private Boolean boss;
          private Date birth;
      
          private String personName;
          private List<String> lists;
          private Map<String,Object> maps;
          private Dog dog;  // 嵌套对象
          private List<Dog> dogs;
      }

2. 松散绑定

就是 personName 字段在配置文件中以多种形式书写,都可以绑定值。
@ConfigurationProperties 支持,@Value 不支持


3. SpEL

@Value 配合 SpE不仅可以绑定简单属性,还能处理非常复杂的表达式和对象操作。
@ConfigurationProperties 不支持,@Value 支持

a. 配置文件内容

java 复制代码
# SpEL 表达式
personDemo:
  id: 1
  name: "zhangsan"
  address: 北京
  boss: true

b. PersonDemo实体类

java 复制代码
// 复杂 SpEL 表达式
@Component
public class PersonDemo {

    @Value("${personDemo.name}")
    private String name;

    // 数学运算:计算结果为 15
    @Value("#{10 + 5}")
    private Integer rendomNumber;

    // 将配置的值转为大写
    @Value("#{'${personDemo.name}'.toUpperCase()}")
    private String uppercaseName;

    // 调用静态方法:生成 0-100 的随机数
    @Value("#{T(java.lang.Math).random() * 100}")
    private Double randomScore;

    // 三元运算符:条件表达式
    @Value("#{${personDemo.id} > 0 ? 'active' : 'inactive'}")
    private String status;

    @Value("#{${personDemo.boss} ? '领导' : '员工'}")
    private String role;

    // 正则表达式匹配
    @Value("#{personDemo.name matches '[a-zA-Z]+'}")
    private Boolean isNameValid;

    // 列表操作
    @Value("#{{'apple', 'banana', 'orange'}}")
    private List<String> fruits;
}

4. JSR303 数据校验

@ConfigurationProperties 支持,@Value 不支持

a. 配置文件内容

java 复制代码
# JSR303 数据校验
user-demo:
  id: 2
  name: lisi
  email: 123456789@qq.com
  phone: 13345678910
  accepted: true
  birth: 2026/2/20

b. User实体类

java 复制代码
@Component
@ConfigurationProperties(prefix = "user-demo")
@Validated // 启用校验  JSR303 数据校验
public class UserDeno {

    @NotNull(message = "ID不能为空")
    @Min(value = 1, message = "ID必须大于0")
    @Max(value = 10, message = "ID不能超过10")
    private Integer id;

    @NotBlank(message = "姓名不能为空")
    @Size(min = 2, max = 10, message = "姓名长度必须在2-10之间")
    private String name;

    @Email(message = "邮箱格式不正确")
    private String email;

    @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
    private String phone;

    @AssertTrue(message = "必须接收协议")
    private Boolean accepted;

    @Future(message = "生日必须是将来时间")
    private Date birth;
}

5. 复杂类型封装

在person中的dog对象等属性的封装
@ConfigurationProperties 支持,@Value 不支持

@Value获取值和@ConfigurationProperties获取值比较


@PropertySource&@ImportResource&@Bean

@PropertySource

@PropertySource:加载指定的配置文件

  1. 新建一个 application-dev.properties 配置文件
java 复制代码
user-demo.id=2
user-demo.name=李四
user-demo.email=3025147478@qq.com
user-demo.phone=15032722309
user-demo.accepted=true
user-demo.birth=2026/2/20
  1. 在UserDemo实体类上添加 @PropertySource 注解,指定配置文件
java 复制代码
// @PropertySource指定加载配置文件
@PropertySource(value = {"classpath:application-dev.properties"})
@Component
@ConfigurationProperties(prefix = "user-demo")
@Validated // 启用校验  JSR303 数据校验
public class UserDemo {

    @NotNull(message = "ID不能为空")
    @Min(value = 1, message = "ID必须大于0")
    @Max(value = 10, message = "ID不能超过10")
    private Integer id;

    @NotBlank(message = "姓名不能为空")
    @Size(min = 2, max = 10, message = "姓名长度必须在2-10之间")
    private String name;

    @Email(message = "邮箱格式不正确")
    private String email;

    @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
    private String phone;

    @AssertTrue(message = "必须接收协议")
    private Boolean accepted;

    @Future(message = "生日必须是将来时间")
    private Date birth;
}

@ImportResource

@ImportResource:导入Spring的配置文件,让配置文件里面的内容生效;

Spring Boot里面没有Spring的配置文件,我们自己编写的配置文件,也不能自动识别;

想让Spring的配置文件生效,加载进来,在启动类上加**@ImportResource 注解**

  1. 在service包下创建 HelloService.java
java 复制代码
public interface HelloService {
    public void hello();
}
  1. 在service.impl下创建HelloServiceImpl.java
java 复制代码
public class HelloServiceImpl implements HelloService {
    @Override
    public void hello() {
        System.out.println("你好");
    }
}
  1. 创建Spring配置文件:applicationContext.xml
XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="helloService" class="com.qcby.springBootDemoYml.service.impl.HelloServiceImpl"/>
</beans>
  1. 在启动类上添加**@ImportResource 注解**
java 复制代码
@SpringBootApplication
// 导入spring的配置类让其生效
@ImportResource(locations = {"classpath:applicationContext.xml"})
public class SpringBootDemoYml {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootDemoYml.class, args);
    }
}
  1. 控制台输出:你好

@Bean

添加@Bean注解后,不在需要 applicationContext.xml 配置文件了,且不需要使用@ImportResource 注解。

  1. 创建WordService.java
java 复制代码
public interface WordService {
    public void helloWord();
}
  1. 创建WordServiceImpl.java
java 复制代码
public class WordServiceImpl implements WordService {
    @Override
    public void helloWord() {
        System.out.println("你好,世界!");
    }
}
  1. 创建WordConfig.java
java 复制代码
@Configuration // 声明当前是配置类
public class WordConfig {
    @Bean // 只能声明在方法上
    public WordService wordServiceBean(){
        System.out.println("wordConfig配置类");
        return new WordServiceImpl();
    }
}
  1. 控制台输出:

wordConfig配置类 你好,世界!


配置文件占位符

占位符使用 ${} 形式。

随机数

java 复制代码
${random.value}、${random.int}、${random.long}
${random.int(10)}、${random.int(0,100)}
  1. 创建Parent实体类,并绑定值

    java 复制代码
    @Component
    @ConfigurationProperties(prefix = "parent")
    public class Parent {
        private Integer id;
        private String name;
        private Integer age;
        private Date birth;
        private Boolean boss;
        private Map<String, Object> maps;
        private List<String> lists;
        private Dog dog;
    
        // 提供无参构造、有参构造、Getter和setter对象,以及重新toString
    }
  2. 在application.yml配置文件中写属性值

    java 复制代码
    # 配置文件占位符
    
    parent:
      id: ${random.int}
      name: "zhaoliu \n ${random.uuid}"
      age: 20
      birth: 2028/12/12
      boss: true
      maps: {email: 3025147478@qq.com, phone: 11111}
      lists:
        - 花花
        - 草草
      dog:
        name: ${parent.name:wangwu}小黄 # 若没有配置parent下的name属性值,默认使用wangwu;若配置类值,则使用配置的值
        age: ${random.int(3,5)} # 生成0到5之间的随机整数

多Profile文件

外部指令优先级 > 配置文件

在配置文件中指定运行环境

有两种多配置文件形式:

  • properties:application-{profile}.properties

    在主配置文件application.properties中指定运行环境

    java 复制代码
    # 多配置文件
    spring.profiles.active=dev
  • yml:在application.yml中配置多个端口

    java 复制代码
    # 多配置文件
    server:
      port: 8085
    
    spring:
      profiles:
        active: dev
    ---
    server:
      port: 8084
    spring:
      profiles: dev
    ---
    server:
      port: 8086
    spring:
      profiles: prod # 指定属于那个环境


在外部指定运行环境

java 复制代码
# java -jar 打包的项目名.jar --spring.profiles.active=环境名称
java -jar springbootdemoyml-1.0-SNAPSHOT.jar --spring.profiles.active=prod

配置文件加载位置

springboot启动会扫描一下位置的application.properties或者application.yml文件作为Spring boot的默认配置文件;

SpringBoot会从这四个位置全部加载主配置文件;互补配置:

  • --file:./config/
  • --file:./
  • --classpath:/config/
  • --classpath:/

如果项目中存在这四个位置下的配置文件,加载顺序为:-file:./config/ > -file:./ > -classpath:/config/ > -classpath:/


外部配置加载顺序

命令行参数: 多个配置用空格分开; --配置项=值

  1. 在D:\code2024\application.properties,放在一个配置文件(端口号:8083),在外部命令行中运行这个环境

    java 复制代码
    # java -jar 打包的项目名.jar --spring.config.location=外部位置\application.properties
    
    java -jar springbootdemoyml-1.0-SNAPSHOT.jar --spring.config.location=D:\code2024\application.properties
  2. 在命令行中指定端口和路径
    注意:在Spring Boot 2.x 之后,不在使用 --server.context-path 这个命令,而是使用 --server.servlet.context-path。

    java 复制代码
    # java -jar 打包的项目名.jar --server.port=端口号 --server.servlet.context-path=路径
    
    java -jar springbootdemoyml-1.0-SNAPSHOT.jar --server.port=8087 --server.servlet.context-path=/abc
相关推荐
学海无涯书山有路2 小时前
Android FragmentContainerView 新手详解(Java 版)
android·java·开发语言
XiYang-DING3 小时前
【Java SE】数据类型、变量、类型转换、运算符以及程序逻辑控制
java·开发语言
廋到被风吹走3 小时前
【Spring】Spring Cloud OpenFeign 深度解析:动态代理、Ribbon集成与Hystrix降级
spring·spring cloud·ribbon
闻哥3 小时前
Redis 避坑指南:从命令到主从的全链路踩坑实录
java·数据库·redis·缓存·面试·springboot
Jinkxs3 小时前
基于 Java 的消息队列选型年度总结:RabbitMQ、RocketMQ、Kafka 实战对比
java·kafka·java-rocketmq·java-rabbitmq
独自破碎E3 小时前
JDK版本的区别
java·开发语言
悟空码字4 小时前
SpringBoot深度整合高德地图,构建高性能位置服务
java·springboot·高德地图·编程技术·后端开发
千金裘换酒4 小时前
栈和队列定义及常用语法 LeetCode
java·开发语言
0x534 小时前
JAVA|智能无人机平台(二)
java·开发语言·无人机