leftso 4758 0 2018-04-01 21:30:38

文章位置:左搜> 编程技术> 正文
Spring Boot 2.0 绑定properties属性资源文件 Spring Boot 2.0 读取配置文件值 Spring Boot 2.0获取配置文件值
自Spring Boot首次发布以来,就可以使用@ConfigurationProperties注释将属性绑定到类。也可以用不同的形式指定属性名称。 例如,person.first-name,person.firstName和PERSON_FIRSTNAME可以互换使用。 我们称这个功能为“宽松绑定”。

不幸的是,在Spring Boot 1.x中,“宽松绑定”实际上有点过于宽松。 确切地定义绑定规则是什么以及什么时候可以使用特定格式是相当困难的。 我们也开始获得有关我们的1.x实施难以解决的问题的报告。 例如,在Spring Boot 1.x中,不可能将项目绑定到java.util.Set。
所以,在Spring Boot 2.0中,我们已经着手重新设计绑定发生的方式。 我们添加了几个新的抽象,并且我们开发了一个全新的绑定API。 在这篇博文中,我们介绍了一些新的类和接口,并描述了为什么添加了它们,它们做了什么,以及如何在自己的代码中使用它们。

Property Sources

如果你一直在使用Spring,你可能很熟悉Environment抽象类。这个接口是一个PropertyResolver,它可以让你从一些底层的PropertySource实现中解析属性。
Spring框架为常见的东西提供PropertySource实现,例如系统属性,命令行标志和属性文件。 Spring Boot 会以对大多数应用程序有意义的方式自动配置这些实现(例如,加载application.properties)。

Configuration Property Sources

Spring Boot 2.0不是直接使用现有的PropertySource接口进行绑定,而是引入了一个新的ConfigurationPropertySource接口。 我们引入了一个新的接口,为我们提供了一个合理的地方来实施放松绑定规则,这些规则以前是活页夹的一部分
接口的主要API非常简单: code:>>ConfigurationProperty getConfigurationProperty(ConfigurationPropertyName name);
还有一个IterableConfigurationPropertySource变相的实现了Iterable 接口,以便您可以发现源包含的所有名称。

通过使用以下代码,可以将Spring Environment调整为ConfigurationPropertySources
Iterable sources = ConfigurationPropertySources.get(environment);
如果您需要它,我们还提供一个简单的MapConfigurationPropertySource实现。

Configuration Property Names

事实证明,如果将其限制为一个方向,放宽属性名称的实现更容易实现。 您应该始终使用规范形式访问代码中的属性,而不管它们在基础源中的表示方式如何。
ConfigurationPropertyName类强制执行这些规范的命名规则,这些规则基本归结为“使用小写的kebab-case名称”。
因此,例如,即使在基础源中使用person.firstName或PERSON_FIRSTNAME,也应该将代码中的属性称为person.first-name。
Origin Support起源支持
一个Origin是Spring Boot 2.0中引入的一个新接口,可以让您精确定位从某个值加载的确切位置。 有许多Origin实现,可能最有用的是TextResourceOrigin。 这提供了加载的资源的详细信息,以及值的行号和列号。
***************************
APPLICATION FAILED TO START
***************************

Description:
Binding to target org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'person' to scratch.PersonProperties failed:

Property: person.name
Value: Joe
Origin: class path resource [application.properties]:1:13
Reason: length must be between 4 and 2147483647


Action:

Update your application's configuration
 

Binder API

Binder类(在org.springframework.boot.context.properties.bind中)可以让你获取一个或多个ConfigurationPropertySource并从它们中绑定一些东西。 更准确地说,一个Binder采用一个Bindable并返回一个BindResult。
Bindable
Bindable可能是现有的Java bean,类类型或复杂的ResolvableType(如List )。 这里有些例子
Bindable.ofInstance(existingBean);
Bindable.of(Integer.class);
Bindable.listOf(Person.class);
Bindable.of(resovableType);

Bindable也用于携带注释信息,但通常不需要关心这一点。

BindResult


绑定器不是直接返回一个绑定对象,而是返回一个名为BindResult的东西。 类似于Java 8 Streams返回Optional的方式,BinderResult表示可能绑定或可能未绑定的内容。

如果您尝试获取未绑定对象的实际结果,则会引发异常。 我们还提供了一些方法,可以让您在没有任何约束或映射到不同类型时提供替代值
var bound = binder.bind("person.date-of-birth",Bindable.of(LocalDate.class));

// Return LocalDate or throws if not bound
bound.get();

// Return a formatted date or "No DOB"
bound.map(dateFormatter::format).orElse("No DOB");

// Return LocalDate or throws a custom exception
bound.orElseThrow(NoDateOfBirthException::new);

Formatting and Conversion 

大多数ConfigurationPropertySource实现将其基础值作为字符串公开。 当Binder需要将源值转换为其他类型时,它将委托给Spring的ConversionService API。
如果您需要调整值的转换方式,则可以自由使用格式化程序注释(如@NumberFormat或@DateFormat)。

Spring Boot 2.0还引入了一些对绑定特别有用的新注释和转换器。 例如,您现在可以将诸如4s之类的值转换为持续时间。 有关详细信息,请参阅org.springframework.boot.convert包。

BindHandler

有时候,绑定时可能需要实现额外的逻辑,而BindHandler接口提供了一个很好的方法来实现这一点。 每个BindHandler都可以实现onStart,onSuccess,onFailure和onFinish方法来覆盖行为。

Spring Boot提供了一些处理程序,主要用于支持现有的@ConfigurationProperties绑定。 例如,ValidationBindHandler可用于对绑定对象应用Validator验证。

@ConfigurationProperties

正如本文开始时提到的,@ConfigurationProperties从一开始就一直是Spring Boot的特色。 @ConfigurationProperties很可能仍然是大多数人执行绑定的方式。

尽管我们重写了整个绑定过程,但大多数人在升级Spring Boot 1.5应用程序时似乎并没有太多问题。 只要您遵循迁移指南中的建议,您应该会发现事情继续良好。
如果您在升级应用程序时发现问题,请在GitHub问题跟踪器上以小样本向他们报告,以便重现问题。

Future Work

我们计划在Spring Boot 2.1中继续开发Binder,我们希望支持的第一个特性是不可变的配置属性。 如果当前需要getter和setter的配置属性可以使用基于构造函数的绑定,那将是非常好的:
public class Person {

	private final String firstName;
	private final String lastName;
	private final LocalDateTime dateOfBirth;

	public Person(String firstName, String lastName,
			LocalDateTime dateOfBirth) {
		this.firstName = firstName;
		this.lastName = lastName;
		this.dateOfBirth = dateOfBirth;
	}

	// getters

}
我们认为构造函数绑定也可以很好地处理Kotlin数据类。

小结
我们希望您能够在Spring Boot 2.0中发现新的绑定功能,并且您会考虑升级现有的Spring Boot应用程序。