Configuration d'application - Métadonnées de configuration Spring

Personnalisation de votre application avec @ConfigurationProperties , comme alternative à l'utilisation de @Value .

Dans l'article

  • Définition et modification des fonctionnalités d'application via application.properties à l'aide de ConfigurationProperties
  • Intégration de application.properties à l'IDE
  • Vérification des paramètres

image

Les différences entre les deux approches sont décrites ici - ConfigurationProperties vs. Valeur
Dans l'image ci-dessus, la composition principale et le principe de fonctionnement. Les composants disponibles du système, ce sont des composants Spring, seules les classes, diverses constantes, variables, etc. peuvent être spécifiées dans le fichier application.properties, et même au moment où l'environnement de développement l'indique, des options seront proposées, des contrôles seront effectués. Lorsque l'application démarre, les valeurs indiquées sont vérifiées pour la conformité avec le type, les restrictions et si tout est satisfaisant, l'application démarre. Par exemple, il est très pratique de configurer la fonctionnalité de l'application à partir de la liste des composants Spring disponibles, ci-dessous je vais vous montrer comment.
Classe de propriété

Pour créer des paramètres d'application à l'aide de ConfigurationProperties, vous pouvez commencer par une classe de propriétés. Il indique en fait les propriétés, les composants du système que nous voulons configurer.

AppProperties.java
 @ConfigurationProperties(prefix = "demo") @Validated public class AppProperties { private String vehicle; @Max(value = 999, message = "Value 'Property' should not be greater than 999") private Integer value; private Map<String,Integer> contexts; private StrategyEnum strategyEnum; private Resource resource; private DemoService service; public String getVehicle() { return vehicle; } public void setVehicle(String vehicle) { this.vehicle = vehicle; } public Map<String, Integer> getContexts() { return contexts; } public void setContexts(Map<String, Integer> contexts) { this.contexts = contexts; } public StrategyEnum getStrategyEnum() { return strategyEnum; } public void setStrategyEnum(StrategyEnum strategyEnum) { this.strategyEnum = strategyEnum; } public Resource getResource() { return resource; } public void setResource(Resource resource) { this.resource = resource; } public DemoService getService() { return service; } public void setService(DemoService service) { this.service = service; } public Integer getValue() { return value; } public void setValue(Integer value) { this.value = value; } @Override public String toString() { return "MyAppProperties{" + "\nvehicle=" + vehicle + "\n,contexts=" + contexts + "\n,service=" + service + "\n,value=" + value + "\n,strategyEnum=" + strategyEnum + '}'; } } 


Dans la classe prefix = "demo" sera utilisé dans application.properties, comme préfixe de la propriété.

Classe d'application et projet SpringApplication pom.xml
 @SpringBootApplication @EnableConfigurationProperties({AppProperties.class}) @ImportResource(value= "classpath:context.xml") public class DemoConfigProcessorApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(DemoConfigProcessorApplication.class, args); AppProperties properties = context.getBean(AppProperties.class); String perform = properties.getService().perform(properties.getVehicle()); System.out.println("perform: " + perform); System.out.println(properties.toString()); } } 

 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>demoConfigProcessor</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>demoConfigProcessor</name> <description>Demo project for Spring Boot Configuration Processor</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.jayway.jsonpath</groupId> <artifactId>json-path</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> 


Puis j'ai déclaré deux bacs à ressort

Contexte de printemps (context.xml)
 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="service1" class="com.example.demoConfigProcessor.MyDemoService1"> <description>Description MyDemoService 1</description> </bean> <bean id="service2" class="com.example.demoConfigProcessor.MyDemoService2"> <description>Description MyDemoService 2</description> </bean> </beans> 


Dans la classe AppProperties, j'ai indiqué un lien vers un service d'application disponible, je vais le changer dans application.properties, j'aurai deux de ses implémentations et j'en connecterai une dans application.properties.

image

Voici leur implémentation

DemoService
 public interface DemoService { String perform(String value); } 

 public class MyDemoService1 implements DemoService { @Override public String perform(String value) { return "Service №1: perform routine maintenance work on <" + value +">"; } } 

 public class MyDemoService2 implements DemoService { @Override public String perform(String value) { return "Service №2: perform routine maintenance work on <" + value +">"; } } 


Cela suffit maintenant pour commencer à personnaliser application.properties. Mais chaque fois que des modifications sont apportées à la classe avec ConfigurationProperties, vous devez reconstruire le projet, après quoi le fichier apparaît dans le projet
\target\classes\META-INF\spring-configuration-metadata.json . En fait, son IDE utilise pour l'édition dans le fichier application.properties. J'indiquerai sa structure dans le lien dans les matériaux. Ce fichier sera créé en fonction de la classe AppProperties. Si vous ouvrez maintenant le fichier application.properties et commencez à taper «démo», l'environnement commencera à afficher les propriétés disponibles

image

Si vous essayez de saisir le mauvais type, l'IDE signalera

image

Même si vous le laissez tel quel et essayez de démarrer l'application, il y aura une erreur complètement distincte

image
Ajout de métadonnées supplémentaires

Métadonnées supplémentaires, c'est uniquement pour la commodité de travailler avec application.properties dans l'EDI, si cela n'est pas nécessaire, vous ne pouvez pas le faire. Pour ce faire, il est possible de spécifier des astuces et autres informations pour l'environnement dans un fichier supplémentaire. Pour ce faire, copiez le fichier spring-configuration-metadata.json créé dans \src\main\resources\META-INF\ et renommez-le en
additional-spring-configuration-metadata.json . Dans ce fichier, je ne serai intéressé que par la section des astuces: []

Il sera possible de lister, par exemple, des valeurs valides pour demo.vehicle

 "hints": [ { "name": "demo.vehicle", "values": [ { "value": "car make A", "description": "Car brand A is allowed." }, { "value": "car make B", "description": "Car brand B is allowed." } ] }] 

Dans le champ "nom", la propriété "demo.vehicle" est indiquée, et dans "valeurs" une liste de valeurs valides. Maintenant, si je reconstruis le projet et accède au fichier application.properties, lorsque j'entre dans demo.vehicle, j'obtiens une liste de valeurs valides

image

Lorsque vous entrez un type différent de celui proposé, mais du même type, l'éditeur mettra en évidence, mais l'application démarrera dans ce cas, car il ne s'agit pas d'une restriction stricte, mais simplement d'un indice.

image

Plus tôt dans le projet, j'ai annoncé deux services MyDemoService1 et MyDemoService2, tous deux implémentant l'interface DemoService, maintenant il est possible de configurer de sorte que seuls les services implémentant cette interface soient accessibles à application.properties et, par conséquent, la classe sélectionnée est initialisée dans la classe AppProperties. Pour ce faire, il existe des fournisseurs, vous pouvez les spécifier dans des métadonnées de configuration de ressort supplémentaires. Il existe plusieurs types de fournisseurs qui peuvent être trouvés dans la documentation, je vais en montrer un exemple, spring-bean-reference . Ce type affiche les noms des beans disponibles dans le projet en cours. La liste est limitée à la classe ou à l'interface de base.

Exemple de fournisseurs pour DemoService:

  "hints": [ { "name": "demo.service", "providers": [ { "name": "spring-bean-reference", "parameters": { "target": "com.example.demoConfigProcessor.DemoService" } } ] } ] 

Après cela, dans application.properties pour le paramètre demo.service, un choix de deux services sera disponible, vous pouvez voir leur description (description de la définition).

image

Il est maintenant pratique de choisir le bon service, de modifier la fonctionnalité de l'application. Il y a un point pour les paramètres d'objet, Spring a besoin d'un peu d'aide pour convertir la chaîne spécifiée dans les paramètres en objet. Pour ce faire, une petite classe est héritée de Converter.

ServiceConverter
 @Component @ConfigurationPropertiesBinding public class ServiceConverter implements Converter<String, DemoService> { @Autowired private ApplicationContext applicationContext; @Override public DemoService convert(String source) { return (DemoService) applicationContext.getBean(source); } } 


Le diagramme de classes de projet montre comment ces services sont séparés de l'application principale et accessibles via AppProperties.

image
Propriété de validation
Aux champs de la classe AppProperties, vous pouvez ajouter des vérifications disponibles dans le cadre de JSR 303. J'ai écrit à ce sujet ici . Cela se traduira par un fichier de configuration d'application vérifiable et pratique.

Sortie console

image

Structure du projet

image

Fichier complet additional-spring-configuration-metadata.json

métadonnées de configuration de ressort supplémentaires
 { "groups": [ { "name": "demo", "type": "com.example.demoConfigProcessor.AppProperties", "sourceType": "com.example.demoConfigProcessor.AppProperties" } ], "properties": [ { "name": "demo.contexts", "type": "java.util.Map<java.lang.String,java.lang.Integer>", "sourceType": "com.example.demoConfigProcessor.AppProperties" }, { "name": "demo.vehicle", "type": "java.lang.String", "sourceType": "com.example.demoConfigProcessor.AppProperties" } ], "hints": [ { "name": "demo.vehicle", "values": [ { "value": "car make A", "description": "Car brand A is allowed." }, { "value": "car make B", "description": "Car brand B is allowed." } ] }, { "name": "demo.service", "providers": [ { "name": "spring-bean-reference", "parameters": { "target": "com.example.demoConfigProcessor.DemoService" } } ] } ] } 


Matériaux de métadonnées de configuration

Source: https://habr.com/ru/post/fr430256/


All Articles