使用@ConfigurationPropertiesSpring Boot,可以轻松地从外部源(尤其是本地配置文件)加载配置。这些文件可以包含 自定义的复杂数据结构 ,因此非常适合我们不想在源代码或数据库中维护的静态数据。
我们的应用程序中需要一些结构化的静态数据。在我们构建了将数据存储在数据库中并允许用户自己维护数据的完整功能之前,静态数据也许是一种解决方法。或者,我们只需要一种方法来轻松维护和访问很少更改的数据,而无需将其存储在数据库中的开销。
用例可能是:
通过其 @ConfigurationProperties功能 ,Spring Boot支持从一个或多个配置文件访问结构化数据。
在本文中,我们将看一下:
我们将以“ Quote of the Day”用例为例(实际上,我是在几周前将其构建为向我之前的团队告别的:)。
本文随附 GitHub上的 示例代码。
将静态数据存储在配置文件中
首先,我们创建一个quotes.yml包含我们的静态数据的YAML文件:
<b>static</b>: quotes: - text: <font>"A clever person solves a problem. A wise person avoids it."</font><font> author: </font><font>"Albert Einstein"</font><font> - text: </font><font>"Adding manpower to a late software project makes it later."</font><font> author: </font><font>"Fred Brooks"</font><font> </font>
如果您更喜欢YAML的属性文件,则可以使用它。使用YAML表示嵌套的数据结构更容易。
在我们的例子中,每个引用都有一个文本和一个作者。每个引用将稍后在一个Quote对象中表示。
请注意,我们为数据加上了前缀static:quotes。这是创建唯一名称空间的必要条件,因为Spring Boot稍后将合并此配置文件的内容及其其余配置。
让Spring Boot意识到配置文件
现在,我们必须使Spring Boot知道此配置文件。我们可以通过在spring.config.location每次启动Spring Boot应用程序时设置系统属性来做到这一点:
-Dspring.config.location=./,./quotes.yml
这告诉Spring Boot 在当前文件夹中搜索一个application.properties或application.yml文件(这是默认设置),并另外加载该文件quotes.yml。
这是Spring Boot加载YAML文件并在应用程序中公开内容所需要做的一切。
访问静态数据
首先,我们需要一个Quote数据结构,用作配置数据的容器:
<b>public</b> <b>class</b> Quote { <b>private</b> String text; <b>private</b> String author; <b>public</b> Quote() { } <font><i>// getters and setters omitted</i></font><font> } </font>
该Quote类只有简单的String属性。如果我们有更复杂的数据类型,则可以使用 自定义转换器 将配置参数(始终为Strings)转换为自定义类型。
然后,我们利用Spring Boot的@ConfigurationProperties功能将静态数据绑定到QuotesProperties对象:
@Component @ConfigurationProperties(<font>"static"</font><font>) <b>public</b> <b>class</b> QuotesProperties { <b>private</b> <b>final</b> List<Quote> quotes; <b>public</b> QuotesProperties(List<Quote> quotes) { <b>this</b>.quotes = quotes; } <b>public</b> List<Quote> getQuotes(){ <b>return</b> <b>this</b>.quotes; } } </font>
这就是我们的名称空间前缀起作用的地方。将QuotesProperties类绑定到命名空间static和quotes在配置文件结合同名领域前缀。
当配置属性的绑定失败时,Spring Boot在错误消息中有点不透明。您可能会收到错误消息,例如Binding to target ... failed ... property was left unbound不知道根本原因。
就我而言,根本原因始终是我没有在充当配置属性(在本例中为)的数据结构的类之一中提供默认构造函数以及getter和setter方法Quote。Spring Boot需要一个无参数的构造函数以及getter和setter来填充数据。
验证对静态数据的访问
为了测试我们的静态数据是否按预期工作,我们可以创建一个简单的 集成测试 :
@SpringBootTest( properties = { <font>"spring.config.location = ./,file:./quotes.yml"</font><font> } ) <b>class</b> QuotesPropertiesTest { @Autowired <b>private</b> QuotesProperties quotesProperties; @Test <b>void</b> staticQuotesAreLoaded() { assertThat(quotesProperties.getQuotes()).hasSize(2); } } </font>
该测试最重要的部分是设置spring.config.location属性以告诉Spring Boot拾取我们的quotes.yml文件。
然后,我们可以简单地注入QuotesPropertiesbean并断言它包含我们期望的引号。
访问静态数据
在安装了QuotesPropertiesbean并对其进行了测试之后,我们现在可以简单地将其注入任何其他bean中,以执行我们需要的引号。例如,我们可以构建一个调度程序,每5秒记录一次随机报价:
@Configuration @EnableScheduling <b>public</b> <b>class</b> RandomQuotePrinter { <b>private</b> <b>static</b> <b>final</b> Logger logger = LoggerFactory.getLogger(RandomQuotePrinter.<b>class</b>); <b>private</b> <b>final</b> Random random = <b>new</b> Random(); <b>private</b> <b>final</b> QuotesProperties quotesProperties; <b>public</b> RandomQuotePrinter(QuotesProperties quotesProperties) { <b>this</b>.quotesProperties = quotesProperties; } @Scheduled(fixedRate = 5000) <b>void</b> printRandomQuote(){ <b>int</b> index = random.nextInt(quotesProperties.getQuotes().size()); Quote quote = quotesProperties.getQuotes().get(index); logger.info(<font>"'{}' - {}"</font><font>, quote.getText(), quote.getAuthor()); } } </font>