1. Въведение
Spring Boot има много полезни функции, включително външна конфигурация и лесен достъп до свойствата, дефинирани във файловете със свойства . По-ранен урок описва различни начини, по които това може да се направи.
Сега ще разгледаме по-подробно анотацията @ConfigurationProperties .
2. Настройка
Този урок използва доста стандартна настройка. Започваме с добавяне на spring-boot-starter-parent като родител в нашия pom.xml :
org.springframework.boot spring-boot-starter-parent 2.2.2.RELEASE
За да можем да проверяваме свойствата, дефинирани във файла, също се нуждаем от внедряване на JSR-303 и валидаторът на хибернация е един от тях.
Нека го добавим и към нашия pom.xml :
org.hibernate hibernate-validator 6.0.16.Final
Страницата „Първи стъпки с Hibernate Validator“ съдържа повече подробности.
3. Прости свойства
Официалната документация съветва да изолираме свойствата на конфигурацията в отделни POJO .
Така че нека започнем с това:
@Configuration @ConfigurationProperties(prefix = "mail") public class ConfigProperties { private String hostName; private int port; private String from; // standard getters and setters }
Използваме @Configuration, така че Spring създава Spring bean в контекста на приложението.
@ConfigurationProperties работи най-добре с йерархични свойства, които всички имат един и същ префикс; затова добавяме префикс на поща .
Структурата Spring използва стандартни Java bean setter, така че трябва да декларираме setters за всяко от свойствата.
Забележка: Ако не използваме @Configuration в POJO , тогава трябва да добавим @EnableConfigurationProperties (ConfigProperties.class) в основния клас на приложение Spring, за да обвържем свойствата в POJO:
@SpringBootApplication @EnableConfigurationProperties(ConfigProperties.class) public class EnableConfigurationDemoApplication { public static void main(String[] args) { SpringApplication.run(EnableConfigurationDemoApplication.class, args); } }
Това е! Spring автоматично ще обвърже всяко свойство, дефинирано в нашия файл с свойства, което има префикс mail и същото име като едно от полетата в класа ConfigProperties .
Spring използва някои спокойни правила за свързващи свойства. В резултат на това всички варианти са обвързани със свойството hostName :
mail.hostName mail.hostname mail.host_name mail.host-name mail.HOST_NAME
Следователно можем да използваме следния файл със свойства, за да зададем всички полета:
#Simple properties [email protected] mail.port=9000 [email protected]
3.1. Пролетно зареждане 2.2
От Spring Boot 2.2 Spring намира и регистрира класове @ConfigurationProperties чрез сканиране на път на класа . Следователно не е необходимо да анотирате такива класове с @Component (и други мета-анотации като @Configuration) или дори да използвате @EnableConfigurationProperties:
@ConfigurationProperties(prefix = "mail") public class ConfigProperties { private String hostName; private int port; private String from; // standard getters and setters }
Скенерът на classpath, активиран от @SpringBootApplication, намира класа ConfigProperties , въпреки че не сме коментирали този клас с @Component.
В допълнение, ние можем да използваме за @ConfigurationPropertiesScan анотация за сканиране на потребителски места за класове конфигурация за недвижими имоти:
@SpringBootApplication @ConfigurationPropertiesScan("com.baeldung.configurationproperties") public class EnableConfigurationDemoApplication { public static void main(String[] args) { SpringApplication.run(EnableConfigurationDemoApplication.class, args); } }
По този начин Spring ще търси класове свойства на конфигурацията само в пакета com.baeldung.properties .
4. Вложени свойства
Можем да имаме вложени свойства в Списъци, Карти и Класове.
Нека създадем нов клас Credentials, който да използваме за някои вложени свойства:
public class Credentials { private String authMethod; private String username; private String password; // standard getters and setters }
Също така трябва да се актуализира ConfigProperties клас да използват Списък, а Карта и идентификационни данни за класа:
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 }
Следният файл със свойства ще зададе всички полета:
#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. Използване на @ConfigurationProperties по метод @Bean
Можем също така да използвате @ConfigurationProperties анотацията на @Bean -annotated методи.
Този подход може да бъде особено полезен, когато искаме да обвържем свойствата с компонент на трета страна, който е извън нашия контрол.
Нека създадем прост клас Item , който ще използваме в следващия пример:
public class Item { private String name; private int size; // standard getters and setters }
Сега нека видим как можем да използваме @ConfigurationProperties на метод @Bean , за да обвържем екстернализираните свойства с екземпляра Item :
@Configuration public class ConfigProperties { @Bean @ConfigurationProperties(prefix = "item") public Item item() { return new Item(); } }
Следователно, всяко свойство с префикс на елемент ще бъде картографирано в екземпляра на елемент, управляван от контекста Spring.
6. Проверка на собствеността
@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.
Обърнете внимание, че всички полета на ImmutableCredentials са окончателни. Също така, няма методи за задаване.
Освен това е важно да се подчертае, че за да използваме свързването на конструктора, трябва изрично да активираме нашия конфигурационен клас или с @EnableConfigurationProperties, или с @ConfigurationPropertiesScan .
9. Заключение
В тази статия разгледахме анотацията @ConfigurationProperties и подчертахме някои от полезните функции, които тя предоставя, като спокойно свързване и Bean Validation.
Както обикновено, кодът е достъпен в Github.