Panduan untuk @ConfigurationProperties in Spring Boot

1. Pengenalan

Spring Boot mempunyai banyak ciri berguna termasuk konfigurasi luaran dan akses mudah ke sifat yang ditentukan dalam fail sifat . Tutorial sebelumnya menerangkan pelbagai cara di mana ini dapat dilakukan.

Kami sekarang akan meneroka anotasi @ConfigurationProperties dengan lebih terperinci.

2. Persediaan

Tutorial ini menggunakan persediaan yang agak standard. Kita mulakan dengan menambahkan spring-boot-starter-parent sebagai induk dalam pom.xml kami :

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

Untuk dapat mengesahkan sifat yang ditentukan dalam file, kami juga memerlukan implementasi JSR-303, dan hibernate-validator adalah salah satunya.

Mari tambahkan juga ke pom.xml kami :

 org.hibernate hibernate-validator 6.0.16.Final  

Halaman "Bermula dengan Hibernate Validator" mempunyai lebih banyak butiran.

3. Sifat Sederhana

Dokumentasi rasmi menasihatkan bahawa kami mengasingkan sifat konfigurasi ke dalam POJO yang berasingan .

Oleh itu mari kita mulakan dengan melakukan itu:

@Configuration @ConfigurationProperties(prefix = "mail") public class ConfigProperties { private String hostName; private int port; private String from; // standard getters and setters }

Kami menggunakan @Configuration sehingga Spring membuat Spring bean dalam konteks aplikasi.

@ConfigurationProperties berfungsi paling baik dengan sifat hierarki yang semuanya mempunyai awalan yang sama; oleh itu, kami menambah awalan mel .

Kerangka Spring menggunakan setter kacang Jawa standard, jadi kita mesti menyatakan setter untuk setiap sifat.

Catatan: Sekiranya kita tidak menggunakan @Configuration dalam POJO, maka kita perlu menambahkan @EnableConfigurationProperties (ConfigProperties.class) di kelas aplikasi Spring utama untuk mengikat sifat ke dalam POJO:

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

Itu sahaja! Spring akan secara automatik mengikat apa-apa harta yang ditakrif dalam fail harta kita yang mempunyai awalan mel dan nama yang sama sebagai salah satu bidang dalam ConfigProperties kelas .

Spring menggunakan beberapa peraturan santai untuk mengikat sifat. Akibatnya, variasi berikut semuanya terikat dengan nama host nama :

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

Oleh itu, kita dapat menggunakan fail sifat berikut untuk menetapkan semua bidang:

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

3.1. Spring Boot 2.2

Sehingga Spring Boot 2.2, Spring mendapati dan daftar-daftar yang @ConfigurationProperties kelas melalui pengimbasan classpath . Oleh itu, tidak perlu membuat anotasi kelas tersebut dengan @Component (dan meta-anotasi lain seperti @Configuration), atau bahkan menggunakan @EnableConfigurationProperties:

@ConfigurationProperties(prefix = "mail") public class ConfigProperties { private String hostName; private int port; private String from; // standard getters and setters } 

Pengimbas classpath yang diaktifkan oleh @SpringBootApplication menemui kelas ConfigProperties , walaupun kami tidak memberi anotasi kelas ini dengan @Component.

Di samping itu, kita boleh menggunakan yang @ConfigurationPropertiesScan anotasi untuk mengimbas lokasi tersuai untuk kelas harta konfigurasi:

@SpringBootApplication @ConfigurationPropertiesScan("com.baeldung.configurationproperties") public class EnableConfigurationDemoApplication { public static void main(String[] args) { SpringApplication.run(EnableConfigurationDemoApplication.class, args); } }

Dengan cara ini Spring akan mencari kelas harta tanah konfigurasi hanya dalam pakej com.baeldung.properties .

4. Hartanah Bersarang

Kita boleh memiliki sifat bersarang di Daftar , Peta, dan Kelas.

Mari buat kelas Kredensial baru untuk digunakan untuk beberapa sifat bersarang:

public class Credentials { private String authMethod; private String username; private String password; // standard getters and setters }

Kita juga perlu mengemaskini ConfigProperties kelas menggunakan Senarai, yang Peta , dan Bukti kelayakan kelas:

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 }

Fail sifat berikut akan menetapkan semua medan:

#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. Menggunakan @ConfigurationProperties pada Kaedah @Bean

Kami juga boleh menggunakan @ConfigurationProperties anotasi pada @Bean kaedah -annotated.

Pendekatan ini mungkin sangat berguna ketika kita ingin mengikat sifat ke komponen pihak ketiga yang berada di luar kawalan kita.

Mari buat kelas Item mudah yang akan kami gunakan dalam contoh seterusnya:

public class Item { private String name; private int size; // standard getters and setters }

Sekarang mari kita lihat bagaimana kita dapat menggunakan @ConfigurationProperties pada kaedah @Bean untuk mengikat sifat yang diluar dari contoh Item :

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

Akibatnya, setiap item awalan item akan dipetakan ke contoh Item yang dikendalikan oleh konteks Spring.

6. Pengesahan Harta

@ConfigurationProperties provides validation of properties using the JSR-303 format. This allows all sorts of neat things.

For example, let's make the hostName property mandatory:

@NotBlank private String hostName;

Next, let's make the authMethod property from 1 to 4 characters long:

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

Then the port property from 1025 to 65536:

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

Finally, the from property must match an email address format:

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

This helps us reduce a lot of if – else conditions in our code, and makes it look much cleaner and more concise.

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

The Hibernate Validation framework uses standard Java bean getters and setters, so it's important that we declare getters and setters for each of the properties.

7. Property Conversion

@ConfigurationProperties supports conversion for multiple types of binding the properties to their corresponding beans.

7.1. Duration

We'll start by looking at converting properties into Duration objects.

Here we have two fields of type Duration:

@ConfigurationProperties(prefix = "conversion") public class PropertyConversion { private Duration timeInDefaultUnit; private Duration timeInNano; ... }

This is our properties file:

conversion.timeInDefaultUnit=10 conversion.timeInNano=9ns

As a result, the field timeInDefaultUnit will have a value of 10 milliseconds, and timeInNano will have a value of 9 nanoseconds.

The supported units are ns, us, ms, s, m, h and d for nanoseconds, microseconds, milliseconds, seconds, minutes, hours, and days, respectively.

The default unit is milliseconds, which means if we don't specify a unit next to the numeric value, Spring will convert the value to milliseconds.

We can also override the default unit using @DurationUnit:

@DurationUnit(ChronoUnit.DAYS) private Duration timeInDays;

This is the corresponding property:

conversion.timeInDays=2

7.2. DataSize

Similarly, Spring Boot @ConfigurationProperties supports DataSize type conversion.

Let's add three fields of type DataSize:

private DataSize sizeInDefaultUnit; private DataSize sizeInGB; @DataSizeUnit(DataUnit.TERABYTES) private DataSize sizeInTB;

These are the corresponding properties:

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

In this case, the sizeInDefaultUnit value will be 300 bytes, as the default unit is bytes.

The supported units are B, KB, MB, GB, and TB. We can also override the default unit using @DataSizeUnit.

7.3. Custom Converter

We can also add our own custom Converter to support converting a property to a specific class type.

Let's add a simple class Employee:

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

Then we'll create a custom converter to convert this property:

conversion.employee=john,2000

We will convert it to a file of type Employee:

private Employee employee;

We will need to implement the Converter interface, then use @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. Immutable @ConfigurationProperties Binding

As of Spring Boot 2.2, we can use the @ConstructorBinding annotation to bind our configuration properties.

This essentially means that @ConfigurationProperties-annotated classes may now be immutable.

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

As we can see, when using @ConstructorBinding, we need to provide the constructor with all the parameters we'd like to bind.

Perhatikan bahawa semua bidang ImmutableCredentials adalah muktamad. Tidak ada kaedah setter.

Selain itu, penting untuk menekankan bahawa untuk menggunakan pengikat konstruktor, kita perlu secara eksplisit mengaktifkan kelas konfigurasi kita sama ada dengan @EnableConfigurationProperties atau dengan @ConfigurationPropertiesScan .

9. Kesimpulannya

Dalam artikel ini, kami meneroka anotasi @ConfigurationProperties dan menyoroti beberapa ciri berguna yang disediakannya, seperti pengikatan santai dan Pengesahan Kacang.

Seperti biasa, kodnya terdapat di Github.