Рубрики
Без рубрики

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

Краткое и практическое руководство по аннотации @ConfigurationProperties в Spring Boot.

Автор оригинала: baeldung.

1. введение

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

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

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

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

Свойства с пружиной и пружинным загрузчиком

2. Настройка

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


    org.springframework.boot
    spring-boot-starter-parent
    2.4.0
    

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

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


   org.hibernate
   hibernate-validator
   6.0.16.Final

Страница “Начало работы с валидатором Hibernate” содержит более подробную информацию.

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

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

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

@Configuration
@ConfigurationProperties(prefix = "mail")
public class ConfigProperties {
    
    private String hostName;
    private int port;
    private String from;

    // standard getters and setters
}

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

@ConfigurationProperties лучше всего работает с иерархическими свойствами, которые все имеют один и тот же префикс; поэтому мы добавляем префикс mail .

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

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

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

Вот и все! Spring автоматически свяжет любое свойство, определенное в файле свойств, которое имеет префикс mail и то же имя, что и одно из полей в ConfigProperties class .

Spring использует некоторые смягченные правила для свойств привязки. В результате все следующие варианты привязаны к свойству Имя хоста :

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

Поэтому мы можем использовать следующий файл свойств для установки всех полей:

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

3.1. Пружинный ботинок 2.2

Начиная с Spring Boot 2.2 , Spring находит и регистрирует @ConfigurationProperties классы с помощью сканирования пути к классам . Поэтому нет необходимости аннотировать такие классы с помощью @Component (и других мета-аннотаций, таких как @Configuration), или даже использовать свойства @EnableConfigurationProperties:

@ConfigurationProperties(prefix = "mail") 
public class ConfigProperties { 

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

    // standard getters and setters 
}

Сканер путей к классам, включенный @SpringBootApplication , находит свойства Config класса, хотя мы не аннотировали этот класс с помощью @Component.

Кроме того, мы можем использовать аннотацию @Configurationproperties для сканирования пользовательских местоположений для классов свойств конфигурации:

@SpringBootApplication
@ConfigurationPropertiesScan("com.baeldung.configurationproperties")
public class EnableConfigurationDemoApplication { 

    public static void main(String[] args) {   
        SpringApplication.run(EnableConfigurationDemoApplication.class, args); 
    } 
}

Таким образом, Spring будет искать классы свойств конфигурации только в пакете com.baeldung.properties .

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

Мы можем иметь вложенные свойства в Списки, Карты, и Занятия.

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

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

    // standard getters and setters
}

Нам также необходимо обновить свойства Config класса, чтобы использовать List, a Map и Учетные данные класса:

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 -аннотированные методы.

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

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

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 обеспечивает проверку свойств с использованием формата JSR-303. Это позволяет делать всевозможные аккуратные вещи.

Например, давайте сделаем свойство 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 в нашем коде и делает его намного чище и лаконичнее.

Если какая-либо из этих проверок завершится неудачно, то основное приложение не сможет запуститься с IllegalStateException .

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

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

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

7.1. Продолжительность

Мы начнем с преобразования свойств в Длительность объекты .

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

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

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

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

conversion.timeInDefaultUnit=10
conversion.timeInNano=9ns

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

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

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

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

@DurationUnit(ChronoUnit.DAYS)
private Duration timeInDays;

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

conversion.timeInDays=2

7.2. Размер данных

Аналогично, Пружинный ботинок @ConfigurationProperties поддерживает DataSize преобразование типов.

Давайте добавим три поля типа Размер данных :

private DataSize sizeInDefaultUnit;

private DataSize sizeInGB;

@DataSizeUnit(DataUnit.TERABYTES)
private DataSize sizeInTB;

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

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

В этом случае размер В Единицах Измерения По Умолчанию значение будет равно 300 байтам, так как единица измерения по умолчанию-байты.

Поддерживаемые единицы измерения: B, КБ, МБ, ГБ и ТБ. Мы также можем переопределить единицу измерения по умолчанию, используя @DataSizeUnit.

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

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

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

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

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

conversion.employee=john,2000

Мы преобразуем его в файл типа Employee :

private Employee employee;

Нам нужно будет реализовать интерфейс Converter , а затем использовать @ConfigurationPropertiesBinding аннотацию для регистрации нашего пользовательского Конвертера :

@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

Начиная с Spring Boot 2.2, мы можем использовать аннотацию @ConstructorBinding для привязки наших свойств конфигурации .

По сути, это означает, что @ConfigurationProperties -аннотированные классы теперь могут быть неизменяемыми .

@ConfigurationProperties(prefix = "mail.credentials")
@ConstructorBinding
public class ImmutableCredentials {

    private final String authMethod;
    private final String username;
    private final String password;

    public ImmutableCredentials(String authMethod, String username, String password) {
        this.authMethod = authMethod;
        this.username = username;
        this.password = password;
    }

    public String getAuthMethod() {
        return authMethod;
    }

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }
}

Как мы видим, при использовании @ConstructorBinding, нам нужно предоставить конструктору все параметры, которые мы хотели бы привязать.

Обратите внимание, что все поля ImmutableCredentials являются окончательными. Кроме того, нет никаких методов настройки.

Кроме того, важно подчеркнуть, что для использования привязки конструктора нам необходимо явно включить наш класс конфигурации либо с помощью @EnableConfigurationProperties , либо с помощью @ConfigurationPropertiesScan .

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

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

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