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 .