Guide de @ConfigurationProperties in Spring Boot

Guide de @ConfigurationProperties in Spring Boot

1. introduction

Une fonctionnalité pratique de Spring Boot estexternalized configuration and easy access to properties defined in properties files. Un précédentarticle décrivait différentes manières de faire cela.

Nous allons maintenant explorer plus en détail l'annotation@ConfigurationProperties.

Lectures complémentaires:

Un guide rapide sur Spring @Value

Apprenez à utiliser l'annotation Spring @Value pour configurer des champs à partir de fichiers de propriétés, de propriétés système, etc.

Read more

Propriétés avec ressort et botte de printemps

Didacticiel sur l'utilisation des fichiers de propriétés et des valeurs de propriétés dans Spring.

Read more

2. Installer

Cet article utilise une configuration assez standard. Nous commençons par ajouterspring-boot-starter-parent comme parent dans nospom.xml:



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

Pour pouvoir valider les propriétés définies dans le fichier, nous avons également besoin d’une implémentation de JSR-303. hibernate-validator en fait partie.

Ajoutons-le également à nospom.xml:


   org.hibernate
   hibernate-validator
   6.0.16.Final

La pagegetting started with Hibernate Validator contient plus de détails.

3. Propriétés simples

La documentation officielle conseille d'isoler les propriétés de configuration dans des POJO. séparés

Alors commençons par faire ça:

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

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

    // standard getters and setters
}

Nous utilisons@Configuration pour que Spring crée un bean Spring dans le contexte de l'application.

Nous utilisons également@PropertySource pour définir l'emplacement de notre fichier de propriétés. Sinon, Spring utilise l'emplacement par défaut (classpath:application.properties).

@ConfigurationProperties works best with hierarchical properties that all have the same prefix. Nous ajoutons donc un préfixe demail.

La structure Spring utilise des paramètres de configuration de beans Java standard. Il est donc essentiel de déclarer les paramètres de configuration pour chacune des propriétés.

Remarque: Si nous n'utilisons pas@Configuration in le POJO, alors nous devons ajouter@EnableConfigurationProperties(ConfigProperties.class) in la classe d'application Spring principale pour lier les propriétés dans le POJO:

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

C'est ça! 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 utilise des règles assouplies pour les propriétés de liaison. Les variations suivantes sont donc toutes liées à la propriétéhostName:

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

Nous pouvons utiliser le fichier de propriétés suivant pour définir tous les champs:

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

4. Propriétés imbriquées

On peut avoir des propriétés imbriquées dansLists, Maps, etClasses.

Créons une nouvelle classeCredentials à utiliser pour certaines propriétés imbriquées:

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

    // standard getters and setters
}

Nous mettons également à jour la classeConfigProperties pour utiliser unList, aMap et la classeCredentials:

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
}

Le fichier de propriétés suivant définira tous les champs:

#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. Utilisation de@ConfigurationProperties sur une méthode@Bean

Nous pouvons également utiliser l'annotation@ConfigurationProperties sur les méthodes annotées@Bean.

Cette approche peut être particulièrement utile lorsque nous voulons lier des propriétés à un composant tiers qui est hors de notre contrôle.

Créons une simple classeItem que nous utiliserons dans l'exemple suivant:

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

    // standard getters and setters
}

Voyons maintenant comment nous pouvons utiliser@ConfigurationProperties sur une méthode@Bean pour lier des propriétés externalisées à l'instanceItem:

@Configuration
public class ConfigProperties {

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

De cette façon, toute propriété avec préfixe d'élément sera mappée à l'instanceItem gérée par le contexte Spring.

6. Validation de la propriété

@ConfigurationProperties provides validation of properties using the JSR-303 format. Cela permet toutes sortes de choses intéressantes.

Par exemple, rendons la propriétéhostName obligatoire:

@NotBlank
private String hostName;

Et la propriétéauthMethod de 1 à 4 caractères:

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

Et la propriétéport de 1025 à 65536:

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

Enfin, la propriétéfrom doit correspondre au format d'une adresse e-mail:

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

Cela nous aide à réduire beaucoup de conditionsif – else dans notre code et le rend beaucoup plus propre et concis.

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

Le framework Hibernate Validation utilise des getters et des setters Java bean standard, il est donc important que nous déclarions des getters et des setters pour chacune des propriétés.

7. Conversion de propriété

@ConfigurationProperties prend en charge la conversion de plusieurs types pour lier les propriétés à leurs beans correspondants.

7.1. Duration

Nous allons commencer par examiner la conversion des propriétés en objetsDuration.

Ici, nous avons deux champs de typeDuration:

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

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

Et notre fichier de propriétés:

conversion.timeInDefaultUnit=10
conversion.timeInNano=9ns

En conséquence, le champtimeInDefaultUnit aura une valeur de 10 millisecondes ettimeInNano aura une valeur de 9 nanosecondes.

Les unités prises en charge sont respectivementns, us, ms, s, m, h etd pour les nanosecondes, microsecondes, millisecondes, secondes, minutes, heures et jours.

L'unité par défaut est les millisecondes, ce qui signifie que si nous ne spécifions pas d'unité à côté de la valeur numérique, Spring convertira la valeur en millisecondes.

Nous pouvons également remplacer l'unité par défaut en utilisant@DurationUnit:

@DurationUnit(ChronoUnit.DAYS)
private Duration timeInDays;

et la propriété correspondante:

conversion.timeInDays=2

7.2. DataSize

De même, Spring Boot@ConfigurationProperties prend en charge la conversion de typeDataSize.

Ajoutons 3 champs de typeDataSize:

private DataSize sizeInDefaultUnit;

private DataSize sizeInGB;

@DataSizeUnit(DataUnit.TERABYTES)
private DataSize sizeInTB;

et les propriétés correspondantes:

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

Dans ce cas, la valeur desizeInDefaultUnit sera de 300 octets, l'unité par défaut étant les octets.

Les unités prises en charge sontB, KB, MB, GB etTB. Nous pouvons également remplacer l'unité par défaut en utilisant@DataSizeUnit.

7.3. PersonnaliséConverter

Nous pouvons également ajouter nos propresConverter personnalisés pour prendre en charge la conversion d'une propriété en un type de classe spécifique.

Ajoutons une classe simpleEmployee:

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

Et nous allons créer un convertisseur personnalisé pour convertir cette propriété:

conversion.employee=john,2000

vers un fichier de typeEmployee:

private Employee employee;

Nous devrons implémenter l'interfaceConverter, puisuse @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. Conclusion

Nous avons exploré l'annotation@ConfigurationProperties et vu certaines des fonctionnalités pratiques qu'elle fournit, comme la liaison détendue et la validation de Bean.

Comme d'habitude, le code est disponibleover on Github.