Руководство по @ConfigurationProperties в Spring Boot

Руководство по @ConfigurationProperties в Spring Boot

1. Вступление

Одна удобная функция Spring Boot -externalized configuration and easy access to properties defined in properties files. Ранееarticle описал различные способы, которыми это можно сделать.

Теперь мы собираемся изучить аннотацию@ConfigurationProperties более подробно.

Дальнейшее чтение:

Краткое руководство по Spring @Value

Научитесь использовать аннотацию Spring @Value для настройки полей из файлов свойств, системных свойств и т. Д.

Read more

Свойства с Spring и Spring Boot

Учебное пособие по работе с файлами свойств и значениями свойств в Spring.

Read more

2. Настроить

Эта статья использует довольно стандартную настройку. Начнем с добавленияspring-boot-starter-parent в качестве родителя в нашpom.xml:



    org.springframework.boot
    spring-boot-starter-parent
    2.1.3.RELEASE
     

Чтобы иметь возможность проверять свойства, определенные в файле, нам также нужна реализация JSR-303. hibernate-validator - один из них.

Давайте также добавим его к нашемуpom.xml:


   org.hibernate
   hibernate-validator
   6.0.16.Final

На страницеgetting started with Hibernate Validator есть более подробная информация.

3. Простые свойства

Официальная документация рекомендует изолировать свойства конфигурации в отдельные POJO.

Итак, начнем с этого:

@Configuration
@PropertySource("classpath:configprops.properties")
@ConfigurationProperties(prefix = "mail")
public class ConfigProperties {

    private String hostName;
    private int port;
    private String from;

    // standard getters and setters
}

Мы используем@Configuration, чтобы Spring создавал bean-компонент Spring в контексте приложения.

Мы также используем@PropertySource для определения местоположения нашего файла свойств. В противном случае Spring использует расположение по умолчанию (classpath:application.properties).

@ConfigurationProperties works best with hierarchical properties that all have the same prefix. Итак, мы добавляем префиксmail.

Среда Spring использует стандартные установщики Java-бинов, поэтому важно, чтобы мы объявили сеттеры для каждого из свойств.

Примечание. Если мы не используем@Configuration in в POJO, тогда нам нужно добавить@EnableConfigurationProperties(ConfigProperties.class) in в основной класс приложения Spring для привязки свойств к POJO:

@SpringBootApplication
@EnableConfigurationProperties(ConfigProperties.class)
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

Это оно! Spring will automatically bind any property defined in our property file that has the prefix mail and the same name as one of the fields in the ConfigProperties class.

Spring использует некоторые смягченные правила для связывания свойств. Таким образом, все следующие варианты связаны со свойствомhostName:

mail.hostName
mail.hostname
mail.host_name
mail.host-name
mail.HOST_NAME

Мы можем использовать следующий файл свойств, чтобы установить все поля:

#Simple properties
[email protected]
mail.port=9000
[email protected]

4. Вложенные свойства

У нас могут быть вложенные свойства вLists, Maps, иClasses.

Давайте создадим новый классCredentials, который будет использоваться для некоторых вложенных свойств:

public class Credentials {
    private String authMethod;
    private String username;
    private String password;

    // standard getters and setters
}

Мы также обновляем классConfigProperties, чтобы использоватьList, aMap и классCredentials:

public class ConfigProperties {

    private String host;
    private int port;
    private String from;
    private List defaultRecipients;
    private Map additionalHeaders;
    private Credentials credentials;

    // standard getters and setters
}

Следующий файл свойств установит все поля:

#Simple properties
[email protected]
mail.port=9000
[email protected]

#List properties
mail.defaultRecipients[0][email protected]
mail.defaultRecipients[1][email protected]

#Map Properties
mail.additionalHeaders.redelivery=true
mail.additionalHeaders.secure=true

#Object properties
mail.credentials.username=john
mail.credentials.password=password
mail.credentials.authMethod=SHA1

5. Использование@ConfigurationProperties в методе@Bean

Мы также можем использовать аннотацию@ConfigurationProperties для аннотированных методов@Bean.

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

Давайте создадим простой классItem, который мы будем использовать в следующем примере:

public class Item {
    private String name;
    private int size;

    // standard getters and setters
}

Теперь давайте посмотрим, как мы можем использовать@ConfigurationProperties в методе@Bean для привязки внешних свойств к экземпляруItem:

@Configuration
public class ConfigProperties {

    @Bean
    @ConfigurationProperties(prefix = "item")
    public Item item() {
        return new Item();
    }
}

Таким образом, любое свойство с префиксом элемента будет сопоставлено с экземпляромItem, управляемым контекстом Spring.

6. Подтверждение собственности

@ConfigurationProperties provides validation of properties using the JSR-303 format. Это позволяет делать разные полезные вещи.

Например, сделаем свойствоhostName обязательным:

@NotBlank
private String hostName;

И свойствоauthMethod длиной от 1 до 4 символов:

@Length(max = 4, min = 1)
private String authMethod;

И свойствоport от 1025 до 65536:

@Min(1025)
@Max(65536)
private int port;

Наконец, свойствоfrom должно соответствовать формату адреса электронной почты:

@Pattern(regexp = "^[a-z0-9._%+-][email protected][a-z0-9.-]+\\.[a-z]{2,6}$")
private String from;

Это помогает нам уменьшить количество условийif – else в нашем коде и делает его более понятным и лаконичным.

If any of these validations fail then the main application would fail to start with an IllegalStateException.

Инфраструктура Hibernate Validation использует стандартные средства получения и установки Java-бина, поэтому важно, чтобы мы объявляли средства получения и установки для каждого свойства.

7. Преобразование собственности

@ConfigurationProperties поддерживает преобразование для нескольких типов для привязки свойств к соответствующим bean-компонентам.

7.1. Durationс

Начнем с преобразования свойств в объектыDuration.

Здесь у нас есть два поля типаDuration:

@ConfigurationProperties(prefix = "conversion")
public class PropertyConversion {

    private Duration timeInDefaultUnit;
    private Duration timeInNano;
    ...
}

И наш файл свойств:

conversion.timeInDefaultUnit=10
conversion.timeInNano=9ns

В результате полеtimeInDefaultUnit будет иметь значение 10 миллисекунд, аtimeInNano будет иметь значение 9 наносекунд.

Поддерживаемые единицы:ns, us, ms, s, m, h иd для наносекунд, микросекунд, миллисекунд, секунд, минут, часов и дней соответственно.

Единица измерения по умолчанию - миллисекунды. Это означает, что если мы не укажем единицу измерения рядом с числовым значением, Spring преобразует значение в миллисекунды.

Мы также можем переопределить единицу измерения по умолчанию, используя@DurationUnit:

@DurationUnit(ChronoUnit.DAYS)
private Duration timeInDays;

и соответствующее свойство:

conversion.timeInDays=2

7.2. DataSizeс

Точно так же Spring Boot@ConfigurationProperties поддерживает преобразование типаDataSize.

Добавим 3 поля типаDataSize:

private DataSize sizeInDefaultUnit;

private DataSize sizeInGB;

@DataSizeUnit(DataUnit.TERABYTES)
private DataSize sizeInTB;

и соответствующие свойства:

conversion.sizeInDefaultUnit=300
conversion.sizeInGB=2GB
conversion.sizeInTB=4

В этом случае значениеsizeInDefaultUnit будет 300 байтов, поскольку единицей измерения по умолчанию являются байты.

Поддерживаемые единицы:B, KB, MB, GB иTB.. Мы также можем изменить единицу измерения по умолчанию, используя@DataSizeUnit..

7.3. ПользовательскийConverter

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

Давайте добавим простой классEmployee:

public class Employee {
    private String name;
    private double salary;
}

И мы создадим специальный конвертер для преобразования этого свойства:

conversion.employee=john,2000

в поле типаEmployee:

private Employee employee;

Нам нужно будет реализовать интерфейсConverter, затемuse @ConfigurationPropertiesBinding annotation to register our custom*Converter*:

@Component
@ConfigurationPropertiesBinding
public class EmployeeConverter implements Converter {

    @Override
    public Employee convert(String from) {
        String[] data = from.split(",");
        return new Employee(data[0], Double.parseDouble(data[1]));
    }
}

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

Мы изучили аннотацию@ConfigurationProperties и увидели некоторые удобные функции, которые она предоставляет, такие как упрощенная привязка и проверка компонентов.

Как обычно, доступен кодover on Github.