likes
comments
collection
share

Spring Boot「32」外部配置元数据

作者站长头像
站长
· 阅读数 13

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 17 天,点击查看活动详情

Spring Boot 应用开发过程中,经常会使用到外部配置文件,例如 application.properties。此时,一般会通过 @ConfigurationProperties 注解,将外部配置文件中的属性映射到 Java bean 中。在今天的文章中,我们将一块儿来学习如何使用 Configuration Processor 生成 JSON 格式的外部配置元数据;然后,我们会展示 IntelliJ IDEA 是如何通过生成的 JSON 元数据来实现属性自动补全的(autocomplete)。

当我们开发 Spring Boot 程序时,或使用其他第三方提供的 Spring Boot 组件时,肯定会遇到外部属性。但通常我们并不了解这些外部属性,某些情况下甚至不知道某些属性的存在。如果应用中使用到的外部属性能够有一个描述性的解释文件,肯定能够提高我们对使用组件或别人对我们提供的应用的理解和掌握。

Spring Boot 提供了 Configuration Processor 机制,来生成外部配置文件的描述性源信息。这种信息不但可以帮制使用者更好地使用外部属性,而且 IDE 等开发工具也可以读取这些信息,以提供自动补全等提高开发效率的功能。

01-生成配置元数据

需要用到如下依赖:

<!-- tag::configuration processor[] -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <version>2.1.6.RELEASE</version>
    <optional>true</optional>
</dependency>
<!-- end::configuration processor[] -->

首先,定义一个 DatabaseProperties 类,用来封装 database 开头的属性。

@ConfigurationProperties(prefix = "database")
public class DatabaseProperties {
    public static class Server {
        /**
         * The IP of the database server
         */
        private String ip;
        /**
         * The Port of the database server.
         * The Default value is 443.
         * The allowed values are in the range 400-4000.
         */
        private int port;
        /** 省略构造器、getter/setter */
    }

    private String username;
    private String password;
    private Server server;
    /** 省略构造器、getter/setter */
}

用于封装的 configuration-metadata.properties 内容如下:

database.username=testdb
database.password=password
database.server.ip=127.0.0.1
database.server.port=8001

然后,创建一个应用类 DatabaseApplication,作为运行程序的容器。

@SpringBootApplication
@EnableConfigurationProperties(DatabaseProperties.class)
@PropertySource("classpath:properties/configuration-metadata.properties")
public class DatabaseApplication {
    /** 忽略其他 */
}

最后,创建测试类,测试是否正确加载外部属性。

@SpringBootTest(classes = {DatabaseApplication.class})
public class DatabasePropertiesIntegrationTest {
    @Autowired
    private DatabaseProperties properties;

    @Test
    public void whenSimplePropertyQueriedThenReturnsPropertyValue() {

        assertThat(properties.getUsername()).isEqualTo("testdb");
        assertThat(properties.getPassword()).isEqualTo("password");
        assertThat(properties.getServer().getIp()).isEqualTo("127.0.0.1");
        assertThat(properties.getServer().getPort()).isEqualTo(8001);

    }
}

在 IntelliJ IDEA 中,如果 classpath 下包含了 configuration-processor,则会自动地在 target\classes\META-INF 下生成元数据文件 spring-configuration-metadata.json。其内容类似于:

{
  "groups": [
    {
      "name": "database",
      "type": "self.samson.example.basic.DatabaseProperties",
      "sourceType": "self.samson.example.basic.DatabaseProperties"
    },
    {
      "name": "database.server",
      "type": "self.samson.example.basic.DatabaseProperties$Server",
      "sourceType": "self.samson.example.basic.DatabaseProperties",
      "sourceMethod": "getServer()"
    }
  ],
  "properties": [
    {
      "name": "database.password",
      "type": "java.lang.String",
      "sourceType": "self.samson.example.basic.DatabaseProperties"
    },
    {
      "name": "database.server.ip",
      "type": "java.lang.String",
      "description": "The IP of the database server",
      "sourceType": "self.samson.example.basic.DatabaseProperties$Server"
    },
    {
      "name": "database.server.port",
      "type": "java.lang.Integer",
      "description": "The Port of the database server. The Default value is 443. The allowed values are in the range 400-4000.",
      "sourceType": "self.samson.example.basic.DatabaseProperties$Server"
    },
    {
      "name": "database.username",
      "type": "java.lang.String",
      "sourceType": "self.samson.example.basic.DatabaseProperties"
    }
  ],
  "hints": []
}

其中的属性解释如下:

  • groups,属性分组,例如上例中的 database 和 database.server。
  • properties,具体属性值,name 为属性名;type 为类型;description 为描述,可根据 javadoc 自动生成;sourceType 为类型信息。
  • hints,是额外的提示信息。

02-IntelliJ IDEA 使用元数据实现代码提示

上述生成的元信息,IDE 也可读取到,并据此提供自动补全提示功能。例如:

Spring Boot「32」外部配置元数据

若要使用 IntelliJ IDEA 实现自动提示自定义 properties 功能,同样需要 spring-boot-configuration-processor 在项目的 classpath 下。

如果我们在 spring-configuration-metadata.json 中加入如下内容,在我们使用对应的属性值时,IDE 会提示我们候选值。

"hints": [
  {
    "name": "database.server.port",
    values: [
      {
        "value": "8001",
        "description": "8001 port"
      },
      {
        "value": "8002",
        "description": "8002 port"
      }
    ]
  }
]

其效果如图所示: Spring Boot「32」外部配置元数据

refs