Una guida ai metadati di configurazione di Spring Boot

1. Panoramica

Quando si scrive un'applicazione Spring Boot, è utile mappare le proprietà di configurazione sui bean Java. Qual è il modo migliore per documentare queste proprietà, però?

In questo tutorial, esploreremo il processore di configurazione Spring Boot e i file di metadati JSON associati che documentano il significato, i vincoli e così via di ciascuna proprietà.

2. Metadati di configurazione

La maggior parte delle applicazioni su cui lavoriamo come sviluppatori deve essere configurabile in una certa misura. Tuttavia, di solito, non capiamo davvero cosa fa un parametro di configurazione, se ha un valore predefinito, se è deprecato e, a volte, non sappiamo nemmeno che la proprietà esiste.

Per aiutarci, Spring Boot genera metadati di configurazione in un file JSON, che ci fornisce informazioni utili su come utilizzare le proprietà. Quindi, i metadati di configurazione sono un file descrittivo che contiene le informazioni necessarie per l'interazione con le proprietà di configurazione.

La cosa veramente bella di questo file è che anche gli IDE possono leggerlo , dandoci il completamento automatico delle proprietà di Spring, così come altri suggerimenti di configurazione.

3. Dipendenze

Per generare questi metadati di configurazione, useremo il processore di configurazione dalla dipendenza spring-boot-configuration-processor .

Quindi, andiamo avanti e aggiungiamo la dipendenza come opzionale :

 org.springframework.boot spring-boot-configuration-processor 2.1.6.RELEASE true 

Questa dipendenza ci fornirà un processore di annotazioni Java invocato quando creiamo il nostro progetto. Ne parleremo in dettaglio più avanti.

È consigliabile aggiungere una dipendenza come opzionale in Maven per impedire che @ConfigurationProperties venga applicato ad altri moduli utilizzati dal nostro progetto.

4. Esempio di proprietà di configurazione

Per vedere il processore in azione, immaginiamo di avere alcune proprietà che dobbiamo includere nella nostra applicazione Spring Boot tramite un bean Java:

@Configuration @ConfigurationProperties(prefix = "database") public class DatabaseProperties { public static class Server { private String ip; private int port; // standard getters and setters } private String username; private String password; private Server server; // standard getters and setters }

Per fare ciò, useremo l' annotazione @ConfigurationProperties . Il processore di configurazione esegue la scansione di classi e metodi con questa annotazione per accedere ai parametri di configurazione e generare metadati di configurazione.

Aggiungiamo un paio di queste proprietà in un file delle proprietà. In questo caso, lo chiameremo databaseproperties-test.properties :

#Simple Properties database.username=baeldung database.password=password

E, giusto per essere sicuri, aggiungeremo anche un test per assicurarci che siamo tutti in fila:

@RunWith(SpringRunner.class) @SpringBootTest(classes = AnnotationProcessorApplication.class) @TestPropertySource("classpath:databaseproperties-test.properties") public class DatabasePropertiesIntegrationTest { @Autowired private DatabaseProperties databaseProperties; @Test public void whenSimplePropertyQueriedThenReturnsPropertyValue() throws Exception { Assert.assertEquals("Incorrectly bound Username property", "baeldung", databaseProperties.getUsername()); Assert.assertEquals("Incorrectly bound Password property", "password", databaseProperties.getPassword()); } }

Abbiamo anche aggiunto le proprietà nidificate database.server.id e database.server.port tramite la classe interna Server . Dovremmo aggiungere la classe interna Server oltre a un field server con i propri getter e setter.

Nel nostro test, facciamo un rapido controllo per assicurarci di poter impostare e leggere con successo anche le proprietà nidificate:

@Test public void whenNestedPropertyQueriedThenReturnsPropertyValue() throws Exception { Assert.assertEquals("Incorrectly bound Server IP nested property", "127.0.0.1", databaseProperties.getServer().getIp()); Assert.assertEquals("Incorrectly bound Server Port nested property", 3306, databaseProperties.getServer().getPort()); }

Ok, ora siamo pronti per utilizzare il processore.

5. Generazione dei metadati di configurazione

Abbiamo accennato in precedenza che il processore di configurazione genera un file: utilizza l'elaborazione delle annotazioni.

Quindi, dopo aver compilato il nostro progetto, vedremo un file chiamato spring-configuration-metadata.json all'interno di target / classes / META-INF :

{ "groups": [ { "name": "database", "type": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties", "sourceType": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties" }, { "name": "database.server", "type": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties$Server", "sourceType": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties", "sourceMethod": "getServer()" } ], "properties": [ { "name": "database.password", "type": "java.lang.String", "sourceType": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties" }, { "name": "database.server.ip", "type": "java.lang.String", "sourceType": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties$Server" }, { "name": "database.server.port", "type": "java.lang.Integer", "sourceType": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties$Server", "defaultValue": 0 }, { "name": "database.username", "type": "java.lang.String", "sourceType": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties" } ], "hints": [] }

Successivamente, vediamo come la modifica delle annotazioni sui nostri Java bean influisce sui metadati.

5.1. Ulteriori informazioni sui metadati di configurazione

Innanzitutto, aggiungiamo commenti JavaDoc su Server .

Secondo, assegniamo un valore predefinito al campo database.server.port e infine aggiungiamo le annotazioni @Min e @Max :

public static class Server { /** * The IP of the database server */ private String ip; /** * The Port of the database server. * The Default value is 443. * The allowed values are in the range 400-4000. */ @Min(400) @Max(800) private int port = 443; // standard getters and setters }

Se controlliamo ora il file spring-configuration-metadata.json , vedremo riflesse queste informazioni aggiuntive:

{ "groups": [ { "name": "database", "type": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties", "sourceType": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties" }, { "name": "database.server", "type": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties$Server", "sourceType": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties", "sourceMethod": "getServer()" } ], "properties": [ { "name": "database.password", "type": "java.lang.String", "sourceType": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties" }, { "name": "database.server.ip", "type": "java.lang.String", "description": "The IP of the database server", "sourceType": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties$Server" }, { "name": "database.server.port", "type": "java.lang.Integer", "description": "The Port of the database server. The Default value is 443. The allowed values are in the range 400-4000", "sourceType": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties$Server", "defaultValue": 443 }, { "name": "database.username", "type": "java.lang.String", "sourceType": "com.baeldung.autoconfiguration.annotationprocessor.DatabaseProperties" } ], "hints": [] }

Possiamo verificare le differenze con i campi database.server.ip e database.server.port . In effetti, le informazioni extra sono molto utili. Di conseguenza, è molto più facile per gli sviluppatori e gli IDE capire cosa fa ogni proprietà.

Dovremmo anche assicurarci di attivare la build per ottenere il file aggiornato. In Eclipse, se selezioniamo l' opzione Build Automatically , ogni azione di salvataggio attiverà una build. In IntelliJ, dovremmo attivare la compilazione manualmente.

5.2. Comprensione del formato dei metadati

Diamo uno sguardo più da vicino al file di metadati JSON e discutiamo i suoi componenti.

I gruppi sono elementi di livello superiore utilizzati per raggruppare altre proprietà, senza specificare un valore stesso. Nel nostro esempio, abbiamo il gruppo di database , che è anche il prefisso delle proprietà di configurazione. Abbiamo anche un gruppo di server , che abbiamo creato tramite una classe interna e raggruppa le proprietà ip e porta .

Le proprietà sono elementi di configurazione per i quali è possibile specificare un valore. Queste proprietà sono impostate nei file .properties o .yml e possono avere informazioni aggiuntive, come valori predefiniti e convalide, come abbiamo visto nell'esempio sopra.

I suggerimenti sono informazioni aggiuntive per aiutare l'utente a impostare il valore della proprietà. Ad esempio, se abbiamo un insieme di valori consentiti per una proprietà, possiamo fornire una descrizione di ciò che fa ciascuno di essi. L'IDE fornirà un aiuto per la competizione automatica per questi suggerimenti.

Ogni componente nei metadati di configurazione ha i propri attributi per spiegare in modo più dettagliato le proprietà di configurazione.

6. Conclusione

In questo articolo, abbiamo esaminato il processore di configurazione Spring Boot e la sua capacità di creare metadati di configurazione. L'utilizzo di questi metadati semplifica notevolmente l'interazione con i nostri parametri di configurazione.

Abbiamo fornito un esempio di metadati di configurazione generati e spiegato in dettaglio il formato e i componenti.

Abbiamo anche visto quanto può essere utile il supporto del completamento automatico sul nostro IDE.

Come sempre, tutti gli snippet di codice menzionati in questo articolo possono essere trovati nel nostro repository GitHub.