Spring Profiles
1. Giới thiệu
Trong hướng dẫn này, chúng ta sẽ tập trung vào việc giới thiệu Profile
trong Spring. Bạn có thể tìm hiểu thêm ở đâu đó trên internet hoặc ngay tại trang chủ chính thống của Spring.
Profile
là một tính năng cốt lõi của Spring Framework - cho phép chúng ta ánh xạ các Bean của mình thành các Profile khác nhau - ví dụ: dev, test và prod
.
Sau đó, chúng ta có thể kích hoạt các profile khác nhau đó trong các môi trường khác nhau để chỉ định việc khởi động các bean mà chúng ta cần.
2. Làm việc với Profile
Sử dụng @Profile trên Bean
Hãy bắt đầu đơn giản và xem xét cách chúng ta có thể làm cho một Bean thuộc một Profile cụ thể.
Chúng ta sử dụng chú thích @Profile
- ánh xạ (mapping) Bean tới profile cụ thể đó; annotation chỉ lấy tên của một (hoặc nhiều) profile.
Hãy xem xét một kịch bản cơ bản: Chúng ta có một bean chỉ nên hoạt động trong quá trình phát triển nhưng không được triển khai trong sản xuất.
Chúng ta chú thích bean đó bằng dev Profile và nó sẽ chỉ hiện diện trong container trong quá trình phát triển. Trong sản xuất, dev đơn giản là sẽ không được hoạt động:
1
2
3
4
5
@Component
@Profile("dev")
public class DevDatasourceConfig{
}
Là một phụ chú nhanh, tên Profile
cũng có thể được đặt trước bằng toán tử NOT, ví dụ: !Dev
để loại trừ chúng khỏi Profile. Trong ví dụ, component chỉ được kích hoạt nếu dev Profile không hoạt động:
1
2
3
4
5
@Component
@Profile("!dev")
public class DevDatasourceConfig {
}
Khai báo Profile trong XML
Profile cũng có thể được cấu hình bằng XML. Thẻ
1
2
3
4
<beans profile="dev">
<bean id="devDatasourceConfig"
class="com.thecorleone.profiles.DevDatasourceConfig" />
</beans>
Thiết lập Profile
Bước tiếp theo là kích hoạt và thiết lập các Profile để các bean tương ứng được đăng ký trong container. Điều này có thể được thực hiện theo nhiều cách khác nhau mà chúng ta sẽ khám phá trong các phần sau.
Kết hơp với WebApplicationInitializer Interface
Trong các ứng dụng web, WebApplicationInitializer
có thể được sử dụng để cấu hình ServletContext
. Đây cũng là một vị trí rất thuận tiện để đặt các active Profile của chúng ta:
1
2
3
4
5
6
7
8
9
10
11
@Configuration
public class MyWebApplicationInitializer
implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.setInitParameter(
"spring.profiles.active", "dev");
}
}
Kết hợp với ConfigurableEnvironment
Chúng ta cũng có thể đặt Profile trực tiếp trên môi trường:
1
2
3
4
@Autowired
private ConfigurableEnvironment env;
...
env.setActiveProfiles("someProfile");
Context Parameter trong web.xml Tương tự, chúng ta có thể xác định active Profile trong file web.xml của ứng dụng web, sử dụng tham số ngữ cảnh (context parameter):
1
2
3
4
5
6
7
8
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/app-config.xml</param-value>
</context-param>
<context-param>
<param-name>spring.profiles.active</param-name>
<param-value>dev</param-value>
</context-param>
Tham số hệ thống - JVM system parameter
Tên Profille cũng có thể được chuyển vào thông qua tham số hệ thống JVM. Các Profile này sẽ được kích hoạt trong quá trình khởi động ứng dụng:
1
-Dspring.profiles.active=dev
Biến môi trường - Environment Variable
Trong môi trường Unix, các cấu hình cũng có thể được kích hoạt thông qua biến môi trường:
1
export spring_profiles_active=dev
Maven Profile
Spring Profile cũng có thể được kích hoạt thông qua Maven Profile bằng cách chỉ định thuộc tính cấu hình spring.profiles.active
. Trong mọi Maven Profile, chúng ta có thể đặt thuộc tính spring.profiles.active
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<spring.profiles.active>dev</spring.profiles.active>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<spring.profiles.active>prod</spring.profiles.active>
</properties>
</profile>
</profiles>
Giá trị của nó sẽ được sử dụng để thay thế trình giữ chỗ @spring.profiles.active@
trong application.properties
:
1
spring.profiles.active=@spring.profiles.active@
Bây giờ chúng ta cần bật tính năng filter tài nguyên trong pom.xml:
1
2
3
4
5
6
7
8
9
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
...
</build>
và thêm thông số -P
để chuyển đổi cấu hình Maven sẽ được áp dụng:
1
mvn clean package -Pprod
Lệnh này sẽ đóng gói ứng dụng cho profile sản phẩm. Nó cũng áp dụng giá trị spring.profiles.active
cho ứng dụng này khi nó đang chạy.
@ActiveProfile trong kiểm thử
Các kiểm thử giúp bạn dễ dàng chỉ định Profile nào đang hoạt động bằng cách sử dụng chú thích @ActiveProfile
để kích hoạt Profile cụ thể:
1
@ActiveProfiles("dev")
Cho đến đây, chúng ta đã xem xét nhiều cách kích hoạt Profile
. Bây giờ chúng ta hãy xem cái nào có mức độ ưu tiên hơn cái kia và điều gì sẽ xảy ra nếu chúng ta sử dụng nhiều hơn một cái, từ mức độ ưu tiên cao nhất đến thấp nhất:
- Context parameter trong web.xml
- WebApplicationInitializer
- JVM System parameter
- Environment variable
- Maven profile
3. Truy cập Active Profile
Các active Profile của Spring thúc đẩy hành vi của chú thích @Profile
để bật/tắt bean. Tuy nhiên, chúng ta cũng có thể truy cập danh sách các active Profile theo chương trình.
Chúng ta có hai cách để làm điều đó, sử dụng Environment hoặc spring.active.profile.
Sử dụng Environment
Chúng ta có thể truy cập các active profile từ đối tượng Enviroment bằng cách:
1
2
3
4
5
6
7
8
9
10
public class ProfileManager {
@Autowired
private Environment environment;
public void getActiveProfiles() {
for (String profileName : environment.getActiveProfiles()) {
System.out.println("Currently active profile - " + profileName);
}
}
}
Sử dụng spring.active.profile
Ngoài ra, chúng ta có thể truy cập các Profile bằng cách chèn thuộc tính spring.profiles.active
:
1
2
@Value("${spring.profiles.active}")
private String activeProfile;
Ở đây, biến ActiveProfile
của chúng ta sẽ chứa tên của Profile hiện đang hoạt động và nếu có nhiều Profile, nó sẽ chứa tên của chúng được phân tách bằng dấu phẩy.
Tuy nhiên, chúng ta nên xem xét điều gì sẽ xảy ra nếu không có active Profile nào cả. Với code của chúng ta ở trên, việc không có active Profile sẽ ngăn không cho tạo ngữ cảnh ứng dụng. Điều này sẽ dẫn đến IllegalArgumentException do trình giữ chỗ bị thiếu để đưa vào biến.
Để tránh điều đó xảy ra, chúng ta có thể xác định một giá trị mặc định:
1
2
@Value("${spring.profiles.active:}")
private String activeProfile;
Và nếu không có Profile
nào đang hoạt động, thì ActiveProfile
của chúng ta sẽ chỉ chứa một chuỗi trống. Nếu chúng ta muốn truy cập danh sách Profile giống như trong ví dụ trước, chúng ta có thể thực hiện bằng cách tách biến ActiveProfile
:
1
2
3
4
5
6
7
8
9
10
public class ProfileManager {
@Value("${spring.profiles.active:}")
private String activeProfiles;
public String getActiveProfiles() {
for (String profileName : activeProfiles.split(",")) {
System.out.println("Currently active profile - " + profileName);
}
}
}
Một ví dụ demo thực tế - Sử dụng Profile để cấu hình nguồn dữ liệu
Bây giờ, những điều cơ bản đã không còn nữa, chúng ta hãy xem một ví dụ thực tế.
Hãy xem xét một tình huống mà chúng ta phải duy trì cấu hình nguồn dữ liệu cho cả dev và production environment. Tạo một interface DatasourceConfig
cần được triển khai bởi cả hai quá trình triển khai nguồn dữ liệu:
1
2
3
4
5
6
7
8
9
10
11
12
13
public interface DatasourceConfig {
public void setup();
}
Sau đây là cấu hình cho dev environment:
@Component
@Profile("dev")
public class DevDatasourceConfig implements DatasourceConfig {
@Override
public void setup() {
System.out.println("Setting up datasource for DEV environment. ");
}
}
Và cấu hình cho production environment:
1
2
3
4
5
6
7
8
@Component
@Profile("production")
public class ProductionDatasourceConfig implements DatasourceConfig {
@Override
public void setup() {
System.out.println("Setting up datasource for PRODUCTION environment. ");
}
}
Bây giờ, hãy tạo một test và inject vào Interface DatasourceConfig
của chúng ta - tùy thuộc vào active Profile, Spring sẽ inject DevDatasourceConfig
hoặc ProductionDatasourceConfig:
1
2
3
4
5
6
7
8
public class SpringProfilesWithMavenPropertiesIntegrationTest {
@Autowired
DatasourceConfig datasourceConfig;
public void setupDatasource() {
datasourceConfig.setup();
}
}
Khi dev Profile đang hoạt động, Spring sẽ inject đối tượng DevDatasourceConfig
và khi gọi phương thức setup()
, ta sẽ được kết quả:
1
Setting up datasourc for DEV environment.
Trong bài viết này, chúng ta đã thảo luận về cách xác định Profile
trên bean và cách kích hoạt Profile
phù hợp trong ứng dụng. Cuối cùng, chúng ta đã xác thực sự hiểu biết của mình về các Profile bằng một ví dụ đơn giản nhưng thực tế.
Với các chi tiết được tổng hợp thông qua bài viết này, chắc chắn bạn đã tích luỹ được riêng cho mình một vốn kiến thức nhất định. Hãy tiếp tục tự nghiên cứu và phát triển thêm nhé.
Bài viết mang tính chất “ghi chú, lưu trữ, chia sẻ và phi lợi nhuận”.
Nếu bạn thấy hữu ích, đừng quên chia sẻ với bạn bè và đồng nghiệp của mình nhé!
Happy coding! 😎 👍🏻 🚀 🔥
Đọc thêm: