Chuyển tới nội dung chính

Kiểm tra ràng buộc dữ liệu

Bộ constraint validation dùng chung cho dữ liệu nghiệp vụ: số điện thoại Việt Nam, toạ độ địa lý, danh sách giá trị cho trước, kèm tiện ích validate thủ công và thông điệp lỗi tiếng Việt/tiếng Anh.

Khi nào sử dụng

  • DTO/entity cần ràng buộc số điện thoại theo định dạng Việt Nam thay vì tự viết @Pattern.
  • Cần validate chuỗi toạ độ địa lý (vĩ độ,kinh độ) trước khi lưu.
  • Cần ràng buộc giá trị nằm trong danh sách cho trước mà không muốn tạo enum cứng.
  • Cần validate dữ liệu ngoài luồng request (batch job, import file, trước khi persist) và nhận kết quả dạng map property -> message.
  • Muốn thông điệp lỗi validation hiển thị bằng tiếng Việt theo ngôn ngữ của ứng dụng.

Cài đặt

Thêm dependency vào pom.xml, không cần khai báo version vì BOM đã quản lý:

<dependency>
<groupId>vn.govex.cloud</groupId>
<artifactId>govex-cloud-validation</artifactId>
</dependency>

Hướng dẫn khai báo parent/BOM và Maven repository xem tại Cài đặt.

Cấu hình

Các validator được Hibernate Validator phát hiện tự động qua ServiceLoader, nên chỉ cần:

  • Có Hibernate Validator trên classpath (ví dụ thông qua spring-boot-starter-validation) là dùng được ngay, không cần khai báo bean.
  • Thông điệp lỗi mặc định của Jakarta/Hibernate Validator đã được ghi đè bằng hai file resource đi kèm (tiếng Việt và tiếng Anh); muốn đổi thông điệp riêng thì khai báo message ngay trên annotation.

Sử dụng

Khai báo ràng buộc trên DTO

Các annotation nằm trong package vn.govex.cloud.api.validation:

import jakarta.validation.constraints.NotBlank;
import vn.govex.cloud.api.validation.EnumValue;
import vn.govex.cloud.api.validation.GeoCoordinate;
import vn.govex.cloud.api.validation.Phone;

public class ContactDTO {

@NotBlank
@Phone
private String phone;

@GeoCoordinate
private String location;

@EnumValue(strValues = {"ACTIVE", "INACTIVE"})
private String status;
}

Ràng buộc được kiểm tra tự động khi controller dùng @Valid:

@PostMapping("/contacts")
public ResultMessage<String> create(@Valid @RequestBody ContactDTO contact) {
return contactService.create(contact);
}

Validate thủ công ngoài luồng request

ValidationResult<ContactDTO> result = ValidationUtils.validateEntity(contact);
if (result.isHasErrors()) {
result.getErrorMsg().forEach((property, message) ->
log.warn("{}: {}", property, message));
}

// Chỉ validate một property cụ thể khi cần
ValidationResult<ContactDTO> phoneResult =
ValidationUtils.validateProperty(contact, "phone");

Ràng buộc tuỳ biến

Cả @Phone@GeoCoordinate đều cho phép truyền regexp riêng nếu nghiệp vụ cần định dạng khác mặc định; @EnumValue nhận danh sách strValues (chuỗi) hoặc intValues (số nguyên).

Lưu ý

  • Annotation thuộc package vn.govex.cloud.api.validation (trong govex-cloud-api) — dependency govex-cloud-validation đã kéo sẵn, không cần khai báo thêm.
  • @Phone chỉ kiểm tra định dạng theo regex mặc định, không xác minh đầu số có thật trên thực tế.
  • Với giá trị null/chuỗi rỗng, @Phone@GeoCoordinate trả về hợp lệ — cần kết hợp @NotBlank nếu bắt buộc nhập.
  • @EnumValue chỉ so khớp giá trị theo danh sách truyền vào; giá trị null không bị coi là lỗi, cần thêm @NotNull nếu bắt buộc.
  • ValidationUtils dùng Validator mặc định của Jakarta Validation (khởi tạo tĩnh), không lấy Validator tuỳ biến từ Spring context; cần custom MessageInterpolator thì dùng Validator riêng.