Перейти к основному содержимому

Руководство по метаданным конфигурации Spring Boot

· 6 мин. чтения

1. Обзор

При написании приложения Spring Boot полезно сопоставлять свойства конфигурации с Java-бинами . Но как лучше всего задокументировать эти свойства?

В этом руководстве мы рассмотрим обработчик конфигурации Spring Boot и связанные с ним файлы метаданных JSON, которые документируют значение каждого свойства, ограничения и т. д.

2. Метаданные конфигурации

Большинство приложений, над которыми мы работаем как разработчики, должны быть в той или иной степени настраиваемыми. Однако, как правило, мы не совсем понимаем, что делает параметр конфигурации, если он имеет значение по умолчанию, если он устарел, а иногда мы даже не знаем, что свойство существует.

Чтобы помочь нам, Spring Boot генерирует метаданные конфигурации в файле JSON, который дает нам полезную информацию о том, как использовать свойства. Итак, метаданные конфигурации — это описательный файл, который содержит необходимую информацию для взаимодействия со свойствами конфигурации.

Самое приятное в этом файле то, что IDE тоже могут его читать, предоставляя нам автозаполнение свойств Spring, а также другие подсказки по настройке.

3. Зависимости

Чтобы сгенерировать эти метаданные конфигурации, мы будем использовать процессор конфигурации из зависимости spring-boot-configuration-processor .

Итак, давайте добавим зависимость как необязательную :

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.1.6.RELEASE</version>
<optional>true</optional>
</dependency>

Эта зависимость предоставит нам обработчик аннотаций Java, вызываемый при сборке нашего проекта. Мы подробно поговорим об этом позже.

Рекомендуется добавить зависимость как необязательную в Maven, чтобы предотвратить применение @ConfigurationProperties к другим модулям, которые использует наш проект.

4. Пример свойств конфигурации

Чтобы увидеть процессор в действии, давайте представим, что у нас есть несколько свойств, которые нам нужно включить в наше приложение Spring Boot через Java-бин:

@Configuration
@ConfigurationProperties(prefix = "database")
public class DatabaseProperties {

public static class Server {

private String ip;
private int port;

// standard getters and setters
}

private String username;
private String password;
private Server server;

// standard getters and setters
}

Для этого мы будем использовать аннотацию @ConfigurationProperties . Процессор конфигурации сканирует классы и методы с этой аннотацией , чтобы получить доступ к параметрам конфигурации и создать метаданные конфигурации.

Давайте добавим пару этих свойств в файл свойств. В этом случае мы назовем его databaseproperties-test.properties :

#Simple Properties
database.username=foreach
database.password=password

И, чтобы быть уверенным, мы также добавим тест, чтобы убедиться, что мы все выстроились в очередь:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = AnnotationProcessorApplication.class)
@TestPropertySource("classpath:databaseproperties-test.properties")
public class DatabasePropertiesIntegrationTest {

@Autowired
private DatabaseProperties databaseProperties;

@Test
public void whenSimplePropertyQueriedThenReturnsPropertyValue()
throws Exception {
Assert.assertEquals("Incorrectly bound Username property",
"foreach", databaseProperties.getUsername());
Assert.assertEquals("Incorrectly bound Password property",
"password", databaseProperties.getPassword());
}

}

Мы также добавили вложенные свойства database.server.id и database.server.port через внутренний класс Server . Мы должны добавить внутренний класс Server , а также полевой сервер с собственным геттером и сеттером.

В нашем тесте давайте сделаем быструю проверку, чтобы убедиться, что мы также можем успешно устанавливать и читать вложенные свойства:

@Test
public void whenNestedPropertyQueriedThenReturnsPropertyValue()
throws Exception {
Assert.assertEquals("Incorrectly bound Server IP nested property",
"127.0.0.1", databaseProperties.getServer().getIp());
Assert.assertEquals("Incorrectly bound Server Port nested property",
3306, databaseProperties.getServer().getPort());
}

Хорошо, теперь мы готовы использовать процессор.

5. Создание метаданных конфигурации

Ранее мы упоминали, что процессор конфигурации создает файл — для этого используется обработка аннотаций.

Итак, после компиляции нашего проекта мы увидим файл с именем spring-configuration-metadata.json внутри target/classes/META-INF :

{
"groups": [
{
"name": "database",
"type": "com.foreach.autoconfiguration.annotationprocessor.DatabaseProperties",
"sourceType": "com.foreach.autoconfiguration.annotationprocessor.DatabaseProperties"
},
{
"name": "database.server",
"type": "com.foreach.autoconfiguration.annotationprocessor.DatabaseProperties$Server",
"sourceType": "com.foreach.autoconfiguration.annotationprocessor.DatabaseProperties",
"sourceMethod": "getServer()"
}
],
"properties": [
{
"name": "database.password",
"type": "java.lang.String",
"sourceType": "com.foreach.autoconfiguration.annotationprocessor.DatabaseProperties"
},
{
"name": "database.server.ip",
"type": "java.lang.String",
"sourceType": "com.foreach.autoconfiguration.annotationprocessor.DatabaseProperties$Server"
},
{
"name": "database.server.port",
"type": "java.lang.Integer",
"sourceType": "com.foreach.autoconfiguration.annotationprocessor.DatabaseProperties$Server",
"defaultValue": 0
},
{
"name": "database.username",
"type": "java.lang.String",
"sourceType": "com.foreach.autoconfiguration.annotationprocessor.DatabaseProperties"
}
],
"hints": []
}

Далее давайте посмотрим, как изменение аннотаций в наших Java-бинах влияет на метаданные.

5.1. Дополнительная информация о метаданных конфигурации

Во-первых, давайте добавим комментарии JavaDoc на сервер .

Во-вторых, давайте зададим значение по умолчанию для поля database.server.port и, наконец, добавим аннотации @Min и @Max :

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.
*/
@Min(400)
@Max(800)
private int port = 443;

// standard getters and setters
}

Если мы сейчас проверим файл spring-configuration-metadata.json , мы увидим эту дополнительную информацию:

{
"groups": [
{
"name": "database",
"type": "com.foreach.autoconfiguration.annotationprocessor.DatabaseProperties",
"sourceType": "com.foreach.autoconfiguration.annotationprocessor.DatabaseProperties"
},
{
"name": "database.server",
"type": "com.foreach.autoconfiguration.annotationprocessor.DatabaseProperties$Server",
"sourceType": "com.foreach.autoconfiguration.annotationprocessor.DatabaseProperties",
"sourceMethod": "getServer()"
}
],
"properties": [
{
"name": "database.password",
"type": "java.lang.String",
"sourceType": "com.foreach.autoconfiguration.annotationprocessor.DatabaseProperties"
},
{
"name": "database.server.ip",
"type": "java.lang.String",
"description": "The IP of the database server",
"sourceType": "com.foreach.autoconfiguration.annotationprocessor.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": "com.foreach.autoconfiguration.annotationprocessor.DatabaseProperties$Server",
"defaultValue": 443
},
{
"name": "database.username",
"type": "java.lang.String",
"sourceType": "com.foreach.autoconfiguration.annotationprocessor.DatabaseProperties"
}
],
"hints": []
}

Мы можем проверить различия с помощью полей database.server.ip и database.server.port . Действительно, дополнительная информация весьма полезна. В результате разработчикам и IDE намного проще понять, что делает каждое свойство.

Мы также должны убедиться, что запускаем сборку для получения обновленного файла. В Eclipse, если мы отметим параметр Build Automatically , каждое действие сохранения будет запускать сборку. В IntelliJ мы должны запускать сборку вручную.

5.2. Понимание формата метаданных

Давайте подробнее рассмотрим файл метаданных JSON и обсудим его компоненты.

Группы — это элементы более высокого уровня, используемые для группирования других свойств без указания самого значения. В нашем примере у нас есть группа базы данных , которая также является префиксом свойств конфигурации. У нас также есть группа серверов , которую мы создали с помощью внутреннего класса и групп свойств IP и порта .

Свойства — это элементы конфигурации, для которых мы можем указать значение. Эти свойства задаются в файлах .properties или .yml и могут содержать дополнительную информацию, например значения по умолчанию и проверки, как мы видели в примере выше.

Подсказки — это дополнительная информация, помогающая пользователю установить значение свойства. Например, если у нас есть набор допустимых значений для свойства, мы можем предоставить описание того, что делает каждое из них. Среда IDE предоставит справку по автоконкурсу для этих подсказок.

Каждый компонент в метаданных конфигурации имеет свои собственные атрибуты для более подробного объяснения свойств конфигурации.

6. Заключение

В этой статье мы рассмотрели процессор конфигурации Spring Boot и его способность создавать метаданные конфигурации. Использование этих метаданных значительно упрощает взаимодействие с параметрами конфигурации.

Мы привели пример сгенерированных метаданных конфигурации и подробно объяснили их формат и компоненты.

Мы также увидели, насколько полезной может быть поддержка автозаполнения в нашей IDE.

Как всегда, все фрагменты кода, упомянутые в этой статье, можно найти в нашем репозитории GitHub .