Inject a Map from a YAML File with Spring – 用Spring从YAML文件中注入一个地图

最后修改: 2020年 6月 29日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this quick tutorial, we’ll learn how to inject a map from a YAML file in Spring Boot.

在这个快速教程中,我们将学习如何在Spring Boot中从YAML文件中注入一个地图

First, we’ll start with a little bit of insight on YAML files in Spring Framework. Then we’ll demonstrate how to bind YAML properties to a Map with a practical example.

首先,我们将从对Spring框架中YAML文件的一点了解开始。然后我们将通过一个实际的例子来演示如何将YAML属性绑定到Map

2. YAML Files in Spring Framework

2.Spring框架中的YAML文件

Using YAML files to store external configuration data is a common practice among Spring developers. Basically, Spring supports YAML documents as an alternative to properties, and uses SnakeYAML under the hood to parse them.

使用YAML文件来存储外部配置数据是Spring开发人员中的一种常见做法。基本上,Spring 支持将 YAML 文档作为属性的替代,并在引擎盖下使用SnakeYAML 来解析它们

Without further ado, let’s see what a typical YAML file looks like:

不多说了,让我们看看一个典型的YAML文件是什么样子的。

server:
  port: 8090
  application:
    name: myapplication
    url: http://myapplication.com

As we can see, the YAML file is self-explanatory and more human-readable. As a matter of fact, YAML provides a fancy and concise way to store hierarchical configuration data.

正如我们所看到的,YAML文件是不言自明的,而且更容易被人阅读。事实上,YAML提供了一种花哨而简洁的方式来存储分层的配置数据。

By default, Spring Boot reads configuration properties from application.properties or application.yml at application startup. However, we can use @PropertySource to load a custom YAML file.

默认情况下,Spring Boot在应用程序启动时从application.propertiesapplication.yml读取配置属性。但是,我们可以使用@PropertySource来加载一个自定义YAML文件

Now that we’re familiar with what a YAML file is, let’s see how to inject YAML properties as a Map in Spring Boot.

现在我们已经熟悉了什么是YAML文件,让我们看看如何在Spring Boot中把YAML属性作为Map注入。

3. How to Inject a Map From a YAML File

3.如何从YAML文件中注入一个Map

Spring Boot has taken data externalization to the next level by providing a handy annotation called @ConfigurationProperties. This annotation is introduced to easily inject external properties from configuration files directly into Java objects.

Spring Boot通过提供一个名为@ConfigurationProperties的方便注解,将数据外部化提升到了一个新的水平。该注解的引入可以轻松地将配置文件中的外部属性直接注入Java对象中

In this section, we’ll focus on how to bind YAML properties into a bean class using the @ConfigurationProperties annotation.

在本节中,我们将重点讨论如何使用@ConfigurationProperties annotation将YAML属性绑定到bean类中。

First, we’ll define some key-value properties in application.yml:

首先,我们将在application.yml中定义一些键-值属性。

server:
  application:
    name: InjectMapFromYAML
    url: http://injectmapfromyaml.dev
    description: How To Inject a map from a YAML File in Spring Boot
  config:
    ips:
      - 10.10.10.10
      - 10.10.10.11
      - 10.10.10.12
      - 10.10.10.13
    filesystem:
      - /dev/root
      - /dev/md2
      - /dev/md4
  users: 
    root:
      username: root
      password: rootpass
    guest:
      username: guest
      password: guestpass

In this example, we’ll try to map application into a simple Map<String, String>. Similarly, we’ll inject config details as a Map<String, List<String>>, users as a Map with String keys, and objects belonging to a user-defined class (Credential) as values.

在这个例子中,我们将尝试把application映射成一个简单的Map<String, String>。类似地,我们将把configdetails注入到一个Map<String, List<String>>,users作为一个Map,带有String键,以及属于用户定义的类(Credential)的对象作为值

Then we’ll create a bean class, ServerProperties, to encapsulate the logic of binding our configuration properties to Maps:

然后我们将创建一个Bean,ServerProperties,来封装将配置属性绑定到Maps的逻辑。

@Component
@ConfigurationProperties(prefix = "server")
public class ServerProperties {

    private Map<String, String> application;
    private Map<String, List<String>> config;
    private Map<String, Credential> users;

    // getters and setters

    public static class Credential {
    	
        private String username;
        private String password;
        
        // getters and setters
        
    }
}

As we can see, we decorated the ServerProperties class with @ConfigurationProperties. That way, we tell Spring to map all the properties with the specified prefix to an object of ServerProperties.

正如我们所见,我们用@ConfigurationProperties装饰了ServerProperties类。这样,我们告诉Spring将所有带有指定前缀的属性映射到ServerProperties的一个对象。

Recall that our app needs to be enabled for configuration properties as well, though this is done automatically in most Spring Boot applications.

回顾一下,我们的应用程序也需要启用配置属性,尽管这在大多数Spring Boot应用程序中都会自动完成

Finally, we’ll test if our YAML properties are properly injected as Maps:

最后,我们将测试我们的YAML属性是否作为Maps被正确注入。

@RunWith(SpringRunner.class)
@SpringBootTest
class MapFromYamlIntegrationTest {

    @Autowired
    private ServerProperties serverProperties;

    @Test
    public void whenYamlFileProvidedThenInjectSimpleMap() {
        assertThat(serverProperties.getApplication())
          .containsOnlyKeys("name", "url", "description");

        assertThat(serverProperties.getApplication()
          .get("name")).isEqualTo("InjectMapFromYAML");
    }

    @Test
    public void whenYamlFileProvidedThenInjectComplexMap() {
        assertThat(serverProperties.getConfig()).hasSize(2);

        assertThat(serverProperties.getConfig()
          .get("ips")
          .get(0)).isEqualTo("10.10.10.10");

        assertThat(serverProperties.getUsers()
          .get("root")
          .getUsername()).isEqualTo("root");
    }

}

4. @ConfigurationProperties vs @Value

4.@ConfigurationProperties@Value对比

Now let’s do a quick comparison of @ConfigurationProperties and @Value.

现在,让我们对@ConfigurationProperties @Value.做一个快速比较。

Despite the fact that both annotations can be used to inject properties from configuration files, they are quite different. The major difference between these two annotations is that each one serves a different purpose.

尽管这两个注解都可以用来从配置文件中注入属性它们是完全不同的。这两个注解的主要区别在于,每一个注解都有不同的目的。

In short, @Value allows us to directly inject a particular property value by its key. However, @ConfigurationProperties annotation binds multiple properties to a particular object, and provides access to the properties through the mapped object.

简而言之,@Value允许我们通过键直接注入特定的属性值。然而,@ConfigurationProperties annotation将多个属性绑定到一个特定对象,并通过映射的对象提供对属性的访问。

In general, Spring recommends using @ConfigurationProperties over @Value when it comes to injecting configuration data. @ConfigurationProperties offers a great way to centralize and group configuration properties in a structured object that we can inject later into other beans.

一般来说,Spring推荐使用@ConfigurationProperties 而不是@Value 来注入配置数据@ConfigurationProperties 提供了一种很好的方式,可以将配置属性集中并分组到一个结构化的对象中,以后我们可以将其注入到其他Bean中。

5. Conclusion

5.总结

In this brief article, we discussed how to inject a Map from a YAML file in Spring Boot. Then we highlighted the difference between @ConfigurationProperties and @Value.

在这篇简短的文章中,我们讨论了如何在Spring Boot中从YAML文件中注入一个Map。然后我们强调了@ConfigurationProperties@Value.之间的区别。

As usual, the complete source code for this article is available over on GitHub.

像往常一样,本文的完整源代码可在GitHub上获得