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 và @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 và @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.