Anwendungskonfiguration - Spring-Konfigurationsmetadaten

Anpassen Ihrer Anwendung mit @ConfigurationProperties als Alternative zur Verwendung von @Value .

Im Artikel

  • Festlegen und Ändern der Anwendungsfunktionalität über application.properties mithilfe von ConfigurationProperties
  • Integration von application.properties in die IDE
  • Einstellungen überprüfen

Bild

Die Unterschiede zwischen den beiden Ansätzen werden hier beschrieben - ConfigurationProperties vs. Wert
Im obigen Bild die Hauptzusammensetzung und das Funktionsprinzip. Verfügbare Komponenten des Systems, dies sind Spring-Komponenten. In der Datei application.properties können nur Klassen, verschiedene Konstanten, Variablen usw. angegeben werden. Selbst wenn die Entwicklungsumgebung dies anzeigt, werden Optionen angeboten und Überprüfungen durchgeführt. Wenn die Anwendung gestartet wird, werden die angegebenen Werte auf Übereinstimmung mit dem Typ und den Einschränkungen überprüft. Wenn alles zufriedenstellend ist, wird die Anwendung gestartet. Zum Beispiel ist es sehr praktisch, die Anwendungsfunktionalität aus der Liste der verfügbaren Spring-Komponenten zu konfigurieren. Im Folgenden werde ich zeigen, wie.
Eigenschaftsklasse

Um Anwendungseinstellungen mit ConfigurationProperties zu erstellen, können Sie mit einer Eigenschaftsklasse beginnen. Es zeigt tatsächlich die Eigenschaften und Systemkomponenten an, die wir konfigurieren möchten.

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 + '}'; } } 


In der Klasse wird prefix = "demo" in application.properties als Präfix für die Eigenschaft verwendet.

SpringApplication-Anwendungsklasse und Projekt 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> 


Dann habe ich zwei Federbehälter deklariert

Frühlingskontext (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> 


In der AppProperties-Klasse habe ich einen Link zu einem verfügbaren Anwendungsdienst angegeben. Ich werde ihn in application.properties ändern, zwei seiner Implementierungen haben und einen davon in application.properties verbinden.

Bild

Hier ist ihre Implementierung

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 +">"; } } 


Dies reicht jetzt aus, um application.properties anzupassen. Wenn jedoch mit ConfigurationProperties Änderungen an der Klasse vorgenommen werden, müssen Sie das Projekt neu erstellen. Anschließend wird die Datei im Projekt angezeigt
\target\classes\META-INF\spring-configuration-metadata.json . Tatsächlich wird seine IDE zum Bearbeiten in der Datei application.properties verwendet. Ich werde seine Struktur im Link in den Materialien angeben. Diese Datei wird basierend auf der AppProperties-Klasse erstellt. Wenn Sie jetzt die Datei application.properties öffnen und mit der Eingabe von "demo" beginnen, werden in der Umgebung die verfügbaren Eigenschaften angezeigt

Bild

Wenn Sie versuchen, den falschen Typ einzugeben, meldet die IDE

Bild

Selbst wenn Sie es so lassen, wie es ist, und versuchen, die Anwendung zu starten, tritt ein völlig eindeutiger Fehler auf

Bild
Hinzufügen zusätzlicher Metadaten

Zusätzliche Metadaten, dies dient nur der Vereinfachung der Arbeit mit application.properties in der IDE. Wenn dies nicht erforderlich ist, können Sie dies nicht tun. Zu diesem Zweck können in einer zusätzlichen Datei Hinweise und andere Informationen für die Umgebung angegeben werden. Kopieren Sie dazu die erstellte Datei spring-configuration-metadata.json nach \src\main\resources\META-INF\ und benennen Sie sie in um
additional-spring-configuration-metadata.json . In dieser Datei interessiert mich nur der Abschnitt mit den Hinweisen: []

Darin können beispielsweise gültige Werte für demo.vehicle aufgelistet werden

 "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." } ] }] 

Im Feld "Name" wird die Eigenschaft "demo.vehicle" und in "values" eine Liste gültiger Werte angezeigt. Wenn ich nun das Projekt neu erstelle und zur Datei application.properties gehe, erhalte ich bei Eingabe von demo.vehicle eine Liste gültiger Werte

Bild

Wenn Sie einen anderen als den vorgeschlagenen Typ eingeben, der jedoch denselben Typ hat, wird der Editor hervorgehoben, in diesem Fall wird jedoch die Anwendung gestartet, da dies keine strenge Einschränkung, sondern nur ein Hinweis ist.

Bild

Zu Beginn des Projekts habe ich zwei Dienste angekündigt: MyDemoService1 und MyDemoService2. Beide implementieren die DemoService-Schnittstelle. Jetzt können Sie konfigurieren, dass nur Dienste, die diese Schnittstelle implementieren, für application.properties zugänglich sind. Dementsprechend wird die ausgewählte Klasse in der AppProperties-Klasse initialisiert. Zu diesem Zweck gibt es Anbieter, die Sie in zusätzlichen Spring-Konfigurations-Metadaten angeben können. Es gibt verschiedene Arten von Anbietern, die in der Dokumentation zu finden sind. Ich werde ein Beispiel für eine spring-bean-reference . Dieser Typ zeigt die Namen der verfügbaren Beans im aktuellen Projekt an. Die Liste ist auf die Basisklasse oder Schnittstelle beschränkt.

Beispiel eines Anbieters für DemoService:

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

Danach steht in application.properties für den Parameter demo.service eine Auswahl von zwei Diensten zur Verfügung, deren Beschreibung Sie sehen können (Beschreibung aus der Definition).

Bild

Jetzt ist es bequem, den richtigen Dienst auszuwählen und die Funktionalität der Anwendung zu ändern. Es gibt einen Punkt für Objekteinstellungen: Spring benötigt ein wenig Hilfe beim Konvertieren der in den Einstellungen angegebenen Zeichenfolge in ein Objekt. Zu diesem Zweck wird eine kleine Klasse von Converter geerbt.

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); } } 


Das Projektklassendiagramm zeigt, wie diese Dienste von der Hauptanwendung getrennt sind und über AppProperties zugänglich sind.

Bild
Validierungseigenschaft
Zu den Feldern der AppProperties-Klasse können Sie im Rahmen von JSR 303 verfügbare Prüfungen hinzufügen. Ich habe hier darüber geschrieben . Dies führt zu einer überprüfbaren, praktischen Anwendungskonfigurationsdatei.

Konsolenausgabe

Bild

Projektstruktur

Bild

Vollständige Datei Additional-Spring-Configuration-Metadata.json

Zusätzliche Federkonfigurations-Metadaten
 { "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" } } ] } ] } 


Konfigurationsmetadatenmaterialien

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


All Articles