VieTopik
Tiếng HànTiếng AnhIT
  • Góc học tập
Tải app
  • Thư viện
  • Luyện thi
  • Cẩm nang
  • Góc học tập
Spring Boot Web APIXây API CRUD
Bài 7/19
5 phút

Validation

Nội dung bài · 5 mục
  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 5.Tóm tắt

Client gửi sản phẩm tên rỗng, giá âm. Nếu API cứ thế lưu vào thì dữ liệu hỏng từ đầu. Validation chặn dữ liệu sai trước khi handler method chạy.

Khái niệm

✅ Validation: bước kiểm tra dữ liệu client gửi lên có hợp lệ không trước khi xử lý.

🔖 Bean Validation: bộ annotation chuẩn của Java gắn lên trường của DTO để khai báo quy tắc, ví dụ @NotBlank, @Positive.

Annotation Quy tắc
@NotBlank bắt buộc có, chuỗi không được rỗng
@Size(max = 100) chuỗi tối đa 100 ký tự
@Positive số lớn hơn 0
@Min(1), @Max(10) số nằm trong khoảng
@Email đúng định dạng email

Ví dụ

// ProductsController.java
package com.shop.api;

import jakarta.validation.*;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/products")
class ProductsController {
    @PostMapping
    public ResponseEntity<String> create(
            @Valid @RequestBody
            CreateProductRequest request) {
        return ResponseEntity.ok(
                "Đã tạo " + request.name());
    }
}

// CreateProductRequest.java
package com.shop.api;

import jakarta.validation.constraints.*;

record CreateProductRequest(
        @NotBlank(message = "Tên không được trống")
        @Size(max = 100)
        String name,

        @Positive(message = "Giá phải lớn hơn 0")
        long price) {
}
  • Quy tắc nằm ngay trên từng trường của DTO, trong package jakarta.validation.constraints.
  • @Valid bảo Spring kiểm tra DTO trước khi gọi method. Sai quy tắc thì trả 400, method không chạy.
  • message đặt câu báo lỗi riêng thay cho câu mặc định.
Đúng Sai POST /api/products DTO đúng quy tắc? Method create chạy, trả 200 Trả 400
Dữ liệu sai bị chặn trước khi vào method

Thử ngay

Giữ các file cũ, thay ProductsController.java và CreateProductRequest.java theo phần Ví dụ, rồi chạy lại server. Tạo file product.json với dữ liệu sai:

{ "name": "", "price": -5 }

Rồi gửi:

curl -i -X POST http://localhost:5000/api/products -H "Content-Type: application/json" -d @product.json

Đoán trước khi chạy: method có chạy tới dòng return ResponseEntity.ok(...) không, và response báo mấy lỗi?

Xem kết quả
HTTP/1.1 400
Content-Type: application/json

{"timestamp":"2026-09-29T04:12:00.819Z","status":400,"error":"Bad Request","path":"/api/products"}

Method không chạy. Spring chặn từ trước và trả 400. Body mặc định không kể lỗi nào, nhưng log của server ghi đủ: Validation failed ... with 2 errors, mỗi lỗi kèm tên trường và câu báo lỗi như "Tên không được trống".

Muốn body có danh sách lỗi, thêm dòng spring.web.error.include-binding-errors=always vào application.properties.

Lỗi hay gặp

Tự kiểm tra bằng if trong từng method. Quy tắc bị chép rải rác, sửa một chỗ dễ quên chỗ khác.

// SAI — quy tắc nằm trong method, phải chép lại ở PUT
// ItemsController.java
package com.shop.api;

import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/items")
class ItemsController {
    @PostMapping
    public ResponseEntity<String> create(
            @RequestParam String name) {
        if (name.isBlank()) {
            return ResponseEntity.badRequest()
                    .body("Tên không được trống");
        }
        return ResponseEntity.ok(name);
    }
}

Đặt quy tắc thành annotation trên DTO thì mọi method dùng DTO đó đều được kiểm tra.

// ĐÚNG — quy tắc nằm trên DTO
// ItemsController.java
package com.shop.api;

import jakarta.validation.*;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/items")
class ItemsController {
    @PostMapping
    public ResponseEntity<String> create(
            @Valid @RequestBody
            CreateItemRequest request) {
        return ResponseEntity.ok(request.name());
    }
}

// CreateItemRequest.java
package com.shop.api;

import jakarta.validation.constraints.*;

record CreateItemRequest(
        @NotBlank(message = "Tên không được trống")
        String name) {
}

Quên @Valid. Annotation trên DTO vẫn còn đó, nhưng không có gì bảo Spring kiểm tra, nên dữ liệu sai vẫn lọt vào method.

Tóm tắt

  • Validation chặn dữ liệu sai trước khi method chạy.
  • Khai báo quy tắc bằng annotation trên DTO: @NotBlank, @Positive, @Size.
  • @Valid trước tham số bật bước kiểm tra, sai thì Spring trả 400.
  • Dùng message để có câu báo lỗi dễ hiểu cho người dùng.

Tự kiểm tra

0/3 câu
Câu 1

DTO có trường @Min(1) @Max(10) int quantity, tham số trong controller có @Valid. Client gửi quantity = 0. Chuyện gì xảy ra?

Câu 2

Muốn email của khách hàng vừa bắt buộc vừa đúng định dạng. Gắn annotation nào?

Câu 3

Quy tắc validation nên đặt ở đâu?

DTOCRUD hoàn chỉnh

Nội dung bài

  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 5.Tóm tắt