上篇文章讲到使用@Value注解每次只能读取一个配置属性,若要整体读取多个属性,或者读取具有某种结构关系的一组属性可使用@ConfigurationProperties注解来处理。

@ConfigurationProperties注解的两种用法:

  1. 修饰属性处理类:当@ConfigurationProperties修饰的类被部署为容器中的Bean时,改注解指定的属性会被注入该Bean的属性。因此,@ConfigurationProperties修饰的类称为“属性处理类”。
  2. 修饰@Bean注解修饰的方法:使用@Bean修饰的方法蒋会配置一个容器中的Bean,而@ConfigurationProperties指定的属性会被注入该Bean的属性。

看不懂没关系,下面会有代码示例。

在使用@ConfigurationProperties时可指定如下属性:

  1. prefix(或value):指定要加载的属性的前缀
  2. ignoreInvaildFields():指定是否忽略无效属性值。比如处理类定义了某个字段的类型是Integer,但在配置文件中的值是abc,这就是无效值。
  3. ignoreUnknowFields():指定是否忽略未知的字段值。如果在配置文件中配置的属性比处理类需要的属性更多,那么多出来的属性就是未知属性。

使用属性处理类获取配置属性

直接来看代码示例:

\resources\application.properties文件内容:

org.crazyit.enabled=true
org.crazyit.name=Crazy Java
org.crazyit.remoteAddress=192.168.1.188
org.crazyit.item.brand=Tesla
org.crazyit.item.comments=Good, Excellent

(使用IDEA开发属性处理类时,添加spring-boot-configuration-processor依赖,IDEA会提供“代码补全”功能。

<!-- 添加该依赖后IDEA可以提供自动补全功能 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>

)

SpringBoot不会自动启用@ConfigurationProperties注解,启用该注解有如下方式:

  1. 为@ConfigurationProperties注解修饰的类加@Component注解
  2. 为@ConfigurationProperties注解修饰的类显式配置成容器中的bean
  3. 使用@EnableConfigurationProperties注解,该注解显式指定一个或多个属性处理类,SpringBoot会启用这些属性处理类上的@ConfigurationProperties注解
  4. 使用@ConfigurationPropertiesScan注解,该注解指定一个或多个包及其子包下所有带@ConfigurationProperties注解的类

@ConfigurationProperties注解修饰的属性处理类代码:

// 指定读取以org.crazyit.*开头的属性
@ConfigurationProperties(prefix = "org.crazyit", ignoreUnknownFields=false)
@Component
public class CrazyitProperties
{
// 指定同名的实例变量和setter方法。SpringBoot会通过反射调用setter方法来完成属性值注入
private boolean enabled;
private String name;
private InetAddress remoteAddress;
private final Item item = new Item();
// 省略getter\setter
public static class Item
{
private String brand;
private List<String> comments = new ArrayList<>(Collections.singleton("GREAT"));
// 省略getter\setter
}
}

控制器类代码示例:

@RestController
public class HelloController
{
private final CrazyitProperties crazyitProperties;
// 依赖注入CrazyitProperties属性处理Bean
@Autowired
public HelloController(CrazyitProperties crazyitProperties)
{
this.crazyitProperties = crazyitProperties;
} @GetMapping
public CrazyitProperties hello()
{
return crazyitProperties;
}
}

运行结果:

属性处理类也支持使用构造器完成属性值注入,但是要额外使用@ConstructorBinding修饰用于执行构造注入的构造器。注意:使用构造器注入,必须使用@EnableConfigurationProperties或者@ConfigurationPropertiesScan注解来启用@ConfigurationProperties注解。

属性处理类示例:

@ConfigurationProperties(prefix = "org.crazyit", ignoreUnknownFields=false)
public class CrazyitProperties
{
private boolean enabled;
private String name;
private InetAddress remoteAddress;
private final Item item; @ConstructorBinding
public CrazyitProperties(boolean enabled, String name, InetAddress remoteAddress, Item item)
{
this.enabled = enabled;
this.name = name;
this.remoteAddress = remoteAddress;
this.item = item;
}
// 省略getter\setter public static class Item
{
private String brand;
private List<String> comments = new ArrayList<>(Collections.singleton("GREAT"));
// 省略getter\setter
}
}

application.yml

org:
crazyit:
enabled: true
name: 哈利波特
remote-address: 192.168.1.188
item:
brand: Apple
comments:
- Good
- Excellent

上面配置的属性为org.crazyit.remote-address与CrazyitProperties类中定义的remoteAddress属性不完全相同,SpringBoot能成功注入吗?

答案是肯定的,因为SpringBoot支持宽松绑定(Relaxed Binding)。它不要求配置的属性名和属性处理类中的属性名完全相同。

宽松绑定的四种情况(这4种情况都能完成注入):

  1. org.crazyit.remote-address
  2. org.crazyit. remoteAddress
  3. org.crazyit. remote_address
  4. ORG_CRAZYIT_REMOTEADDRESS

在*.properties和 *.yml文件中配置List类型的属性有较小的区别:

  1. 在*.properties文件中配置List有2种方式:英文逗号隔开多个值;用标准方括号
  2. 在 *.yml文件中配置List有2种方式:英文逗号隔开多个值;用短横线开头(例子所示)

因此,*.properties和 *.yml文件中,都可以用英文逗号隔开多个值来构建List。

App.java示例

@SpringBootApplication
// 指定扫描org.crazyit.app.config包及其子包下的@ConfigurationProperties注解修饰的类
@ConfigurationPropertiesScan("org.crazyit.app.config")
public class App
{
public static void main(String[] args)
{
// 创建Spring容器、运行Spring Boot应用
SpringApplication.run(App.class, args);
}
}

为容器中的bean注入配置属性

@ConfigurationProperties注解除了可修饰类,还可修饰@Bean注解修饰的方法。

代码示例:Book类

public class Book
{
private String title;
private double price;
private String author;
private List<String> keywords;
// 省略getter、setter
}

代码示例:配置类

@Configuration
public class MyConfig
{
@Bean
// @ConfigurationProperties注解会驱动Spring自动调用该Bean的setter方法
@ConfigurationProperties("fkjava.book")
public Book book()
{
return new Book();
}
}

代码示例:application.yml

fkjava:
book:
title: "美语音标"
price: 128
author: "赖世雄"
keywords:
- 英语
- 音标

代码示例:控制器类

@RestController
public class HelloController
{
private final Book book;
// 通过构造器注入Book对象
@Autowired
public HelloController(Book book)
{
this.book = book;
}
@GetMapping
public Book hello()
{
return book;
}
}

运行结果:

@Value和 @ConfigurationProperties的对比

特征 @ConfigurationProperties @Value
注入的属性个数 批量 单个
宽松绑定 支持 部分支持
SpEL 不支持 支持
元数据支持 支持 不支持

属性转换

SpringBoot内置了常用的类型转换机制,如果在转换失败,则应用启动会失败,并抛出异常。如果要忽略转换失败的属性,可将@ConfigurationProperties注解的ignoreInvaildFields属性设为true(默认是false)。

SpringBoot可自动转换如下类型:Duration、Period、DataSize,并支持为属性值指定单位。

  1. Duration类型可指定的单位:ns纳秒、μs微妙、ms毫秒、s秒、m分钟、h小时、d天。
  2. Period类型可指定的单位:y年、m月、w星期、d天。(例如配置1y3d,代表1年3天)。
  3. DataSize类型可指定的单位:B字节、KB千字节、MB兆字节、GB吉字节、TB太字节

代码示例:属性处理类

// 指定读取以org.crazyit.*开头的属性
@ConfigurationProperties(prefix = "org.crazyit")
@Component
public class CrazyitProperties
{
private Duration timeout;
// @DurationUnit注解指定默认的时间单位
@DurationUnit(ChronoUnit.SECONDS)
private Duration lastTime;
private Period runPeriod;
// @DataSizeUnit注解指定默认的数据单位
@DataSizeUnit(DataUnit.MEGABYTES)
private DataSize maxSize;
// 省略getter、setter
}

代码示例:application.properties

org.crazyit.timeout=30000
# 默认单位是秒
org.crazyit.last-time=45
org.crazyit.run-period=2m5d
org.crazyit.max-size=2

代码示例:控制器类

@RestController
public class HelloController
{
private final CrazyitProperties crazyitProperties;
// 依赖注入CrazyitProperties属性处理Bean
@Autowired
public HelloController(CrazyitProperties crazyitProperties)
{
this.crazyitProperties = crazyitProperties;
} @GetMapping
public Map<String, Object> hello()
{
System.out.println(crazyitProperties.getMaxSize().toKilobytes());
return Map.of("props", crazyitProperties,
"maxSize", crazyitProperties.getMaxSize().toKilobytes());
}
}

运行结果:

校验@ConfigurationProperties

只要为属性处理类添加@Validated注解,并使用JSR303的校验注解修饰需要校验的示例变量,SpringBoot会自动校验配置文件中的属性值。如果某个属性校验不通过,应用会启动失败,并用FailureAnalyzer显式校验错误。

如果属性处理类包含复合类型的属性,且要对复合类型的子属性进行校验,则应为该复合类型的属性添加@Valid注解。

@ConfigurationProperties校验基于JSR303,因此必须添加JSR303依赖,spring-boot-starter-validation依赖库包含了JSR303的依赖,因此要在pom文件中添加以下依赖

<!-- 添加Spring Boot Validation依赖库 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>

属性处理类示例:

// 指定读取以org.crazyit.*开头的属性
@ConfigurationProperties(prefix = "org.crazyit", ignoreUnknownFields=false)
@Component
@Validated
public class CrazyitProperties
{
@NotEmpty
private String name;
@Range(max = 150, min=90, message = "价格必须位于90~150之间")
private double price;
@Pattern(regexp = "[1][3-8][0-9]{9}", message = "必须输入有效的手机号")
private String mobile;
@Valid
private final Item item = new Item();
// 省略getter setter public static class Item
{
@Length(min=5, max=10, message = "品牌名长度必须在5到10个字符")
private String brand;
@Size(min = 1, message = "comments至少包含一个元素")
private List<String> comments = new ArrayList<>(Collections.singleton("GREAT"));
// 省略getter、setter
}
}

代码示例:application.properties

org.crazyit.name=Crazy Java
org.crazyit.price=89
org.crazyit.mobile=13334444
org.crazyit.item.brand=Apple
org.crazyit.item.comments=Great, Excellent

运行结果:

对于使用@ConfigurationProperties修饰@Bean方法的情况,同样可对配置属性进行校验,主要为@Bean方法添加@Validated注解即可。

SpringBoot--如何整体读取多个配置属性及其相关操作的更多相关文章

  1. SpringBoot入门篇--读取资源文件配置

    在项目的开发中,我们知道的是SpringBoot框架大大减少了我们的配置文件,但是还是留下了一个application.properties文件让我们可以进行一些配置.当然这些配置必然是包括服务器的配 ...

  2. 理解中WebAPI的属性和相关操作 FormBody和 FormUri等(WebAPI 二)

    1.FromUri使用 将数据通过url方式传递.我们需要在webapi方法标明,这个参数只接受url中参数的值, $("#Save").click(function () { $ ...

  3. 外部配置属性值是如何被绑定到XxxProperties类属性上的?--SpringBoot源码(五)

    注:该源码分析对应SpringBoot版本为2.1.0.RELEASE 1 前言 本篇接 SpringBoot是如何实现自动配置的?--SpringBoot源码(四) 温故而知新,我们来简单回顾一下上 ...

  4. springboot 入门二- 读取配置信息一

    在上篇入门中简单介绍下springboot启动使用了大量的默认配置,在实际开发过程中,经常需要启动多个服务,那端口如何手动修改呢? 此篇就是简单介绍相关的配置文件信息. Spring Boot允许外部 ...

  5. SpringBoot @Value读取properties文件的属性

    SpringBoot在application.properties文件中,可以自定义属性. 在properties文件中如下示: #自定义属性 mail.fromMail.addr=lgr@163.c ...

  6. SpringBoot配置属性之Migration

    SpringBoot配置属性系列 SpringBoot配置属性之MVC SpringBoot配置属性之Server SpringBoot配置属性之DataSource SpringBoot配置属性之N ...

  7. springboot快速入门(二)——项目属性配置(日志详解)

    一.概述 application.properties就是springboot的属性配置文件 在使用spring boot过程中,可以发现项目中只需要极少的配置就能完成相应的功能,这归功于spring ...

  8. SpringBoot配置属性之Server

    SpringBoot配置属性系列 SpringBoot配置属性之MVC SpringBoot配置属性之Server SpringBoot配置属性之DataSource SpringBoot配置属性之N ...

  9. SpringBoot配置属性转载地址

    SpringBoot配置属性系列 SpringBoot配置属性之MVC SpringBoot配置属性之Server SpringBoot配置属性之DataSource SpringBoot配置属性之N ...

  10. SpringBoot配置属性之其他

    SpringBoot配置属性系列 SpringBoot配置属性之MVC SpringBoot配置属性之Server SpringBoot配置属性之DataSource SpringBoot配置属性之N ...

随机推荐

  1. mac使用pptp的正确方式

    环境:macos mojave 10.14.6 尝试的解决方案: mac自带vpn 结论:已经不支持pptp协议 使用shimo 结论:无用,连接的时候没反应 为了解决不能连接的问题,某老外写的ppt ...

  2. Windows查看端口占用、相应进程、杀死进程等[netstat]

    Windows 通过cmd或powerShell查看端口占用.相应进程.杀死进程等的命令 由于一般开发环境是在windows上,相应的一些测试必然涉及到一些端口的监听与使用.当开发使用的端口被占用后, ...

  3. redis 中文乱码

    查询数据时中文乱码 解决方法: 使用 ./redis-cli 登录的时候加上 --raw参数 ./redis-cli --raw

  4. HarmonyOS运动开发:如何集成百度地图SDK、运动跟随与运动公里数记录

    前言 在开发运动类应用时,集成地图功能以及实时记录运动轨迹和公里数是核心需求之一.本文将详细介绍如何在 HarmonyOS 应用中集成百度地图 SDK,实现运动跟随以及运动公里数的记录. 一.集成百度 ...

  5. Linux系列:聊一聊 SystemV 下的进程间共享内存

    一:背景 1. 讲故事 昨天在分析一个 linux 的 dump 时,看到了这么一话警告,参考如下: 0:000> !eeheap -gc *** WARNING: Unable to veri ...

  6. vue3 基础-data-methods-computed-watch

    本篇来简单了解 vue 的数据, 方法, 计算属性和监听器等相关内容. data ( ) vue 里面的 data ( ) 函数返回一些能供模板 template 直接使用的数据, 以变量的方式进行 ...

  7. 字典(Dictionary) update()方法

    描述 python字典(Dictionary) update()函数吧dict2的键/值对更新到dict里 语法 dict.update(dict2) 参数 dict2 -- 添加到指定字典dict里 ...

  8. Golang相关环境变量

    GOROOT: GO语言的安装路径,linux系统下一般是/usr/local/go GOPATH: 程序员自己的go源码路径,比如开发一个Helloworld的项目,那么它的代码文件夹就应该放在GO ...

  9. 搭建邮局-3.安装邮局前端roundcube和测试

    目录 搭建邮局-1.安装hMailserver和配置邮局 https://www.cnblogs.com/daen/p/16040202.html 搭建邮局-2.添加域名和域名解析 https://w ...

  10. k8s | 重启Kubernetes Pod的几种方式

    前言 在使用 docker 的过程中,我们可以使用docker restart {container_id}来重启容器,但是在 kubernetes 中并没有重启命令(没有 kubectl resta ...