Cấu hình với application.properties
Nội dung bài · 6 mục
Tên cửa hàng, số món tối đa mỗi đơn, chuỗi kết nối database: những giá trị này khác nhau giữa máy dev và server thật. Viết cứng trong code thì mỗi lần đổi phải compile lại. Spring Boot đọc chúng từ file cấu hình.
Khái niệm
⚙️ application.properties: file chứa cấu hình của ứng dụng dạng key=value, được đọc tự động khi khởi động.
🌍 Profile: tên chế độ đang chạy như dev hay prod, quyết định file application-{profile}.properties nào được đọc sau để ghi đè application.properties.
Ví dụ
Thêm hai dòng vào src/main/resources/application.properties:
shop.name=Shop An
shop.max-items-per-order=20Đọc trong controller bằng @Value:
// ShopController.java
package com.shop.api;
import org.springframework.beans.factory.annotation.*;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/shop")
class ShopController {
private final String name;
private final int max;
public ShopController(
@Value("${shop.name}") String name,
@Value("${shop.max-items-per-order}")
int max) {
this.name = name;
this.max = max;
}
@GetMapping
public String get() {
return name + ": tối đa " + max + " món";
}
}@Value("${...}")bảo Spring lấy giá trị của key trong${ }rồi truyền vào tham số constructor.- Dấu
.nối tên các cấp trong key:shop.name. - Spring tự đổi chuỗi
20sang kiểu của tham số, ở đây làint.
Đọc cấu hình vào class
Nhiều giá trị cùng nhóm thì đọc cả nhóm vào một record:
// ShopProperties.java
package com.shop.api;
import org.springframework.boot.context.properties.*;
@ConfigurationProperties("shop")
record ShopProperties(
String name, int maxItemsPerOrder) {
}
// ShopApiApplication.java
package com.shop.api;
import org.springframework.boot.*;
import org.springframework.boot.autoconfigure.*;
import org.springframework.boot.context.properties.*;
@SpringBootApplication
@ConfigurationPropertiesScan
public class ShopApiApplication {
public static void main(String[] args) {
SpringApplication.run(
ShopApiApplication.class, args);
}
}@ConfigurationPropertiesScan bảo Spring tìm các record như vậy và tạo bean
cho chúng. Class cần dùng nhận ShopProperties qua constructor, rồi gọi
shop.maxItemsPerOrder(). Cách này có kiểu rõ ràng, gõ sai tên method thì
báo lỗi compile ngay. Key max-items-per-order trong file vẫn phải khớp với
field maxItemsPerOrder.
Thử ngay
Dùng ShopController ở phần Ví dụ. Tạo file
src/main/resources/application-dev.properties cạnh file cũ:
shop.max-items-per-order=5Chạy server với profile dev (PowerShell đặt tham số -D... trong dấu
nháy kép):
./mvnw spring-boot:run -Dspring-boot.run.profiles=devRồi gọi curl -i http://localhost:5000/api/shop.
Đoán trước khi chạy: số món tối đa in ra là 20 hay 5?
Xem kết quả
HTTP/1.1 200
Content-Type: text/plain;charset=UTF-8
Shop An: tối đa 5 mónLà 5. File của profile dev được đọc sau và ghi đè max-items-per-order.
Còn shop.name không bị ghi đè nên vẫn lấy từ application.properties.
Chạy lệnh thường, không có -Dspring-boot.run.profiles=dev, thì file dev
không được đọc và kết quả là 20.
Lỗi hay gặp
Gõ sai tên key trong file. Với ShopProperties, Spring bỏ qua key lạ mà
không báo lỗi, field giữ giá trị mặc định.
# SAI — thiếu chữ s, maxItemsPerOrder luôn bằng 0
shop.max-item-per-order=20# ĐÚNG — khớp với field maxItemsPerOrder
shop.max-items-per-order=20Với @Value thì ngược lại: key không có trong file làm ứng dụng dừng lúc
khởi động, log báo Could not resolve placeholder.
Để mật khẩu trong application.properties. File này được commit lên
git, ai có code là thấy mật khẩu. Hãy lưu bí mật bằng biến môi trường, ví dụ
SPRING_DATASOURCE_PASSWORD. Spring tự đọc biến này thay cho key
spring.datasource.password.
Tóm tắt
- Cấu hình nằm trong
application.properties, đọc bằng@Value. application-dev.propertiesghi đè giá trị khi chạy với profiledev.- Nhóm cấu hình nên đọc vào record bằng
@ConfigurationProperties. - Không để mật khẩu hay khoá bí mật trong file commit lên git.
Tự kiểm tra
0/3 câuapplication.properties có dòng email.smtp.port=587. Cách nào đọc được số 587 vào tham số int port?
application.properties đặt logging.level.root=WARN, application-dev.properties đặt DEBUG. Chạy với profile dev thì dùng giá trị nào?
Chuỗi kết nối database có mật khẩu thật. Nên lưu ở đâu khi chạy trên server?