Hướng dẫn sử dụng @ConfigurationProperties trong spring boot

Spring boot ra đời và phát triển cung cấp rất nhiều tính năng tiện lợi và một trong số đó là cho phép chúng ta dễ dàng cài đặt và truy xuất các cấu hình trong các tệp cấu hình như  application.properties hay application.yml.

@ConfigurationProperties annotation cho phép truy xuất các thuộc tính được đặt trong các tệp cấu hình một cách tự động và mạnh mẽ. Trong bài viết này chúng ta sẽ cùng nhau tìm thêm nhiều khía cạnh về annotation này.

Setup

Trước khi bắt đầu bài hướng dẫn này chúng ta sẽ phải tạo một project spring boot với các dependency bao gồm spring-boot-starter-parent.

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.0</version>
    <relativePath/>
</parent>

Và để kiểm tra các dữ liệu trong tệp cấu hình thì chúng ta cần thêm hibernate-validator.

<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-validator</artifactId>
   <version>6.0.16.Final</version>
</dependency>

@ConfigurationProperties annotation

Giả sử chúng ta có một configuration class sau

@Configuration
@ConfigurationProperties(prefix = "mail")
public class ConfigProperties {
    
    private String hostName;
    private int port;
    private String from;

    // getter, setter method
}

Chúng ta sử dụng @Configuration annotation để chú thích lên ConfigProperties class đều này sẽ khiến spring khởi tạo ConfigProperties bean và đăng ký với application context.

Nếu không muốn sử dụng @Configuration annotation trên ConfigProperties thì chúng ta có thể thêm @EnableConfigurationProperties(ConfigProperties.class) vào hàm main của spring application.

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

Spring sẽ tự động tìm kiếm các thuộc tính được đặt bên trong application.properties hay application.yml có tiền tố là email và đem chúng tiêm vào các thuộc tính tương ứng trong ConfigProperties class.

Ví dụ application.properties.

[email protected]
mail.port=9000
[email protected]

Như vậy ConfigProperties bean của chúng ta sẽ có giá trị hostName tương ứng là [email protected], port là 9000 và from là [email protected].

@ConfigurationProperties từ Spring Boot 2.2

Kể tử spring boot 2.2, nó sẽ tự động tìm kiếm và đăng ký các @ConfigurationProperties class, do vậy chúng ta không cần chú thích @Configuration hay sử dụng @EnableConfigurationProperties trên main class nữa.

@ConfigurationProperties(prefix = "mail") 
public class ConfigProperties { 

    private String hostName; 
    private int port; 
    private String from; 

    // getter, setter method
}

Trình quét classpath được kích hoạt bởi @SpringBootApplication sẽ tìm thấy class ConfigProperties, ngay cả khi chúng ta không chú thích class này bằng @Configuration.

Ngoài ra chúng ta có thể sử dụng @ConfigurationPropertiesScan để tuỳ biến vị trí mà spring sẽ tìm kiếm các @ConfigurationProperties class.

@SpringBootApplication
@ConfigurationPropertiesScan("com.deft.configurationproperties")
public class EnableConfigurationDemoApplication { 

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

Với cách này thì spring sẽ chỉ tìm kiếm các @ConfigurationProperties class tại com.deft.configurationproperties package.

Nested Properties

Chúng ta có thể có các thuộc tính lồng nhau hoặc thậm chí là các thuộc tính có kiểu List, map v.v

Như ví dụ sau

public class Credentials {
    private String authMethod;
    private String username;
    private String password;

    // getters and setters
}

Chúng ta có một ConfigProperties class chứa các list, map và cả Credentials class.

@ConfigurationProperties(prefix = "mail") 
public class ConfigProperties {

    private String host;
    private int port;
    private String from;
    private List<String> defaultRecipients;
    private Map<String, String> additionalHeaders;
    private Credentials credentials;
 
    // getters and setters
}

Để cài đặt các giá trị cho các thuộc tính trên chúng ta có thể cấu hình trong application.properties như sau

[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

@ConfigurationProperties với bean method

Chúng ta cũng có thể sử dụng @ConfigurationProperties annotation trên các bean method. Điều này sẽ khiến spring tìm kiếm các thuộc tính trong tệp cấu hình và tiêm nó vào bean sắp được khởi tạo bởi bean method.

Giả sử chúng ta có Item class.

public class Item {
    private String name;
    private int size;

    // getters and setters
}

Bây giờ chúng ta có thể sử dụng @ConfigurationProperties để cài đặt các giá trị cho Item bean.

@Configuration
public class ConfigProperties {

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

Tệp cấu hình

item.name=item
item.size=10

Property Validation

@ConfigurationProperties cung cấp cơ chế kiểm định dữ liệu được cấu hình theo chuẩn JSR-303.

Gỉa sử có các thuộc tính sau

// hostname không được rỗng
@NotBlank
private String hostName;

// kích thước của authMethod trong khoảng 1 4
@Length(max = 4, min = 1)
private String authMethod;

// port trong khoảng 1025 đến 65536
@Min(1025)
@Max(65536)
private int port;

// from phải thoải mệnh đề regex sau
@Pattern(regexp = "^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,6}$")
private String from;

Khi chúng ta định nghĩa các thuộc tính trong file cấu hình mà không thoả các điều kiện trên đây thì ứng dụng sẽ không thể khởi động và nó sẽ ném ra IllegalStateException.

Immutable @ConfigurationProperties Binding

Đối với các immutable object thì chúng ta sẽ không thể định nghĩa các setter method và vì vậy mà spring sẽ không thể tiêm các dữ liệu từ tệp cấu hình vào, do đó chúng ta có thể sử dụng @ConstructorBinding để spring có thể tiêm chúng thông qua constructor.

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

Nguồn

https://www.baeldung.com/configuration-properties-in-spring-boot

5 1 vote
Article Rating
Subscribe
Notify of
guest
1 Comment
Newest
Oldest Most Voted
Inline Feedbacks
View all comments
1
0
Would love your thoughts, please comment.x
()
x