转载

springboot入门07 – 配置文件详解

概述

这一篇主要介绍下SpringBoot配置相关的内容。

通过配置文件,我们可以做到如下事情:

  • 修改springboot的默认配置项
  • 添加自定义配置项

SpringBoot使用全局的配置文件,主配置文件名是固定的: application.xxx

springboot的配置文件有多种格式可选,如:.properties,.xml,.yml。

我个人比较喜欢yaml的简洁,所以推荐使用yaml。

yaml的基本语法

下面介绍些yaml的语法

  1. 使用空格缩进来表示结构,相同层级的数据其缩进的长度必定相同:
  worker1:
    name: robin
    age: 27
  worker2:
    name: jane
    age: 22
  1. 支持使用注解,但只支持使用单行注解,注解以“ # ”号开头:
  worker1: # a worker object
    name: robin
    age: 27
  1. 支持直接类型或字符串的列表或数组结构,有两种表达形式:
  • 每个列表成员占一行,以横杠和空格(- )开头
  • 所有列表成员在同一行,被方括号([])包围,列表成员间以逗号和空格分隔
  whiteUrl:
    - www.chobit.org
    - www.zhyea.com
  blackUrl: [www.black.com, www.forbidden.com]
  1. 也支持Map结构,同样也有两种表达形式:
  • 每个KV对占一行,键值用冒号分隔
  • 所有KV对在同一行,被大括号({})包围, KV对之间用逗号和空格分隔,键值用冒号分隔
  worker1: # a worker object
    name: robin
    age: 27
  worker2: {name: jane, age: 22} # another worker object
  1. 通常字符串不需要使用引号,但必要时可以使用单引号(’)或双引号(”),比如需要使用转义字符时
content: 'line /n next line'
  1. 可以使用两个叹号(!!)来强制指定格式(这个感觉用处不大,但是万一用到了呢)
  id: !!int 128
  seq: !!str 11112222
  1. 内容可以重复使用,原始位置的内容用(&标记名)来标记,在引用位置用(*标记名)来引用
  worker1: &robin # a worker object
    name: robin
    age: 27
  worker3: *robin
  1. 如果想在一个文件里面配置不同的profile,可以使用三个横杠“—”将yaml文件分割成多个独立区域,每个区域被视为一个独立的文件。三个点号“…”用来标识文件结尾。
server:
    port: 8081
spring:
    profiles:
        active: test	# 切换配置
---
# 开发环境
spring:
  profiles: dev
---
# 测试环境
spring:
  profiles: test
---
# 生产环境
spring:
  profiles: prod

如示例代码,在一个yaml文件中存在多个独立区域时,使用 spring.profiles 属性来标识配置区域的profile信息。

多环境配置

在主配置文件application.yml之外,还可以有多个外部配置文件,其名称格式固定为 application-{profile}.yml

SpringBoot会根据主配置文件中的 spring.profiles.active 参数来决定加载哪个配置文件。

通过这种方式SpringBoot实现了支持多环境配置,从而能够在不同环境下(开发、测试、生产)进行配置参数的切换。

主配置文件中的 spring.profiles.active 属性还可以有多个值,每个值以逗号进行分割:

spring:
  profiles:
    active: dev,test

这种方式允许我们为不同需求创建不同的配置文件。SpringBoot会依序加载每个值指向的配置文件。

配置文件的加载顺序是主配置文件application.yml, spring.profiles.active 指定的外部配置文件。如有冲突项,后面加载的配置会覆盖前面的。

如果多个外部配置文件有相同的配置项,建议在主配置文件中进行配置。

spring.profiles.active 指定的值无法与任何外部文件匹配,SpringBoot会尝试加载 application-default.yml 文件。

结合@Profile实现内部实例的动态选择

spring.profiles.active参数不仅可以指明要使用哪个外部配置文件,也可以控制内部实例的选择。这需要通过配合 @ Profile 注解实现。

如下例:

    @Profile("prod")
    @Bean
    public Worker tom() {
        return new Worker("Tom", 8);
    }
 
    @Profile("dev")
    @Bean
    public Worker jim() {
        return new Worker("Jim", 8);
    }

如果没有 @ Profile 注解,在启动的时候SpringBoot就会报错,因为为一个Worker类提供了两个实例。但是现在,SpringBoot可以根据 spring.profiles.active 指明的profile和 @ Profile 注解来选择注入哪个实例。

@ Profile 注解可以用于含有 @ Component @ Configuration @ Bean 等注解的类及其方法。

@ Profile 注解也可以有多个值,如下:

    @Profile({"dev", "test"})
    @Bean
    public Worker jim() {
        return new Worker("Jim", 8);
    }

这样,在profile是dev或test时,这个Bean都可以被成功注入。

配置项获取

使用SpringBoot的配置项有两种方式:通过 @ Value 注解或通过 @ ConfigurationProperties 注解。这两种方式各有长处,可根据进行选择。

通过@Value注解获取

@ Value 注解适用于单个配置项的获取,比如我们可以获取当前的外部配置文件的profile:

    @Value("${spring.profiles.active}")
    private String profile;

@ Value 注解的一个优势是可以使用SPEL表达式(关于SPEL表达式,我有整理过: 《SpringBoot SpEL表达式》 ),如下是一个非常粗略的SPEL表达式:

    @Value("#{'token:' + '${custom.token}'}")
    private String token;
    
    //输出结果为:token:zhyeeeeeeee

@ Value 注解的不足之处在于只能获取直接类型的值或字符串,不能映射为复杂类型。

通过@PropertiesConfiguration注解获取

@ PropertiesConfiguration 注解的主要特点是可以将配置映射为对象。因此平时还是通过这种方式获取SpringBoot配置为主。

@ PropertiesConfiguration 注解可应用于类或成员方法。

如下是将应用于类的示例:

@Component
@ConfigurationProperties(prefix = "custom")
public class CustomConfig {
 
    private int id;
 
    private String token;
 
    public int getId() {
        return id;
    }
 
    public void setId(int id) {
        this.id = id;
    }
 
    public String getToken() {
        return token;
    }
 
    public void setToken(String token) {
        this.token = token;
    }
}

从示例代码中可以看到配置类需要有 @ Component 注解或 @ Configuration 注解,以便完成注入。

此外,在使用 @ ConfigurationProperties 注解的时候需要传入注入配置属性的前缀,以便获得配置项的范围。

在成员方法上使用 @ PropertiesConfiguration 注解则是一种更为灵活的方式,能够充分弥补 @ Value 注解的不足,示例如下:

    @Bean
    @ConfigurationProperties(prefix = "custom.worker")
    private Worker getWorker() {
        return new Worker();
    }

注意这里还需要用到 @ Bean 注解,以便将读取到的配置信息注入到实例上。不过不能通过getWorker()方法调用,否则获取的还是一个只有默认值的对象。要使用该实例还是需要通过 @ Autowired 注解来注入。

最后,可以看下我在 GITHUB上的示例应用 ,在里面我尝试了SpringBoot配置的各种应用实践。

就这样。

原文  https://www.zhyea.com/2019/12/09/springboot-base-07-application-config-detail.html
正文到此结束
Loading...