Backend

Xây dựng REST API hoàn chỉnh với Spring Boot 3

SSite Admin
28 tháng 07, 2026 2 phút đọc 94 lượt xem
Xây dựng REST API hoàn chỉnh với Spring Boot 3

Spring Boot 3 chạy trên Java 17+, hỗ trợ virtual threads, GraalVM native image và chuẩn hoá xử lý lỗi theo RFC 7807. Trong bài này, chúng ta xây dựng một REST API quản lý sách hoàn chỉnh: từ khởi tạo dự án, entity, repository cho đến validation và xử lý lỗi.

Khởi tạo dự án

Cách nhanh nhất là dùng Spring Initializr với các dependency Web, Data JPA, ValidationPostgreSQL:

curl https://start.spring.io/starter.zip \
  -d dependencies=web,data-jpa,validation,postgresql \
  -d javaVersion=21 -d type=gradle-project \
  -d artifactId=bookstore -o bookstore.zip

Giải nén, mở trong IDE là bạn đã có một project chạy được ngay với ./gradlew bootRun.

Entity và Repository

Spring Data JPA sinh sẵn toàn bộ thao tác CRUD — bạn chỉ cần khai báo interface, thậm chí viết query bằng tên phương thức:

@Entity
public class Book {
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String title;
    private String author;
    private BigDecimal price;
    // getters & setters
}

public interface BookRepository extends JpaRepository<Book, Long> {
    List<Book> findByAuthorContainingIgnoreCase(String author);
}

REST Controller và validation

Dùng Java record làm DTO kết hợp Bean Validation — request không hợp lệ sẽ tự động trả về 400 Bad Request kèm chi tiết từng field lỗi:

public record CreateBookRequest(
    @NotBlank String title,
    @NotBlank String author,
    @Positive BigDecimal price) {}

@RestController
@RequestMapping("/api/books")
public class BookController {
    private final BookRepository books;

    public BookController(BookRepository books) {
        this.books = books;
    }

    @GetMapping
    public List<Book> all() {
        return books.findAll();
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public Book create(@Valid @RequestBody CreateBookRequest req) {
        var book = new Book(req.title(), req.author(), req.price());
        return books.save(book);
    }

    @GetMapping("/{id}")
    public Book one(@PathVariable Long id) {
        return books.findById(id)
            .orElseThrow(() -> new BookNotFoundException(id));
    }
}
Hạ tầng server vận hành các API trong môi trường production

Xử lý lỗi chuẩn RFC 7807 với ProblemDetail

Spring Boot 3 tích hợp sẵn ProblemDetail — chỉ cần một @RestControllerAdvice là mọi lỗi trả về theo cùng một cấu trúc:

@RestControllerAdvice
class GlobalExceptionHandler {

    @ExceptionHandler(BookNotFoundException.class)
    ProblemDetail handleNotFound(BookNotFoundException ex) {
        var pd = ProblemDetail.forStatusAndDetail(
            HttpStatus.NOT_FOUND, ex.getMessage());
        pd.setTitle("Book not found");
        return pd;
    }
}

Client giờ nhận được response lỗi thống nhất, dễ parse:

{
  "type": "about:blank",
  "title": "Book not found",
  "status": 404,
  "detail": "Book 42 does not exist"
}

Kết luận

Chưa đến 100 dòng code, chúng ta đã có một REST API đầy đủ: CRUD, validation và xử lý lỗi chuẩn hoá. Từ nền tảng này, bạn có thể bổ sung phân trang với Pageable, bảo mật với Spring Security, cache với Redis — tất cả đều là những mảnh ghép quen thuộc trong hệ sinh thái Spring.

S

Site Admin

Engineer and writer. Building things with TypeScript and distributed systems.

Bình luận (0)

Bạn cần đăng nhập bằng Google để bình luận.

Hãy là người bình luận đầu tiên.

Bài viết liên quan

99 Ngày Java — Ngày 58: Optional

Optional là công cụ cho kiểu trả về — không field, không tham số, không bọc collection; chuỗi map/flatMap/filter thay kim tự tháp if; orElse luôn tính tham số còn orElseGet lười, orElseThrow cho “không có là lỗi” — và các anti-pattern isPresent + get, orElse(null).

23 thg 9, 20269 phút9
99 Ngày Spring — Ngày 58: Spring Boot Actuator

Boot 3 mặc định chỉ lộ health; bản đồ endpoint an toàn và nguy hiểm; HealthIndicator tự viết với liveness tách khỏi readiness cho Kubernetes, info từ build và git, metrics Micrometer với tag hữu hạn — và ba lớp khóa: cổng riêng, SecurityFilterChain với EndpointRequest, exclude env/heapdump/threaddump.

23 thg 9, 202610 phút5
So sánh EasyExcel và Apache Fesod: khác biệt thật nằm ở đâu?

Fesod là hậu duệ của EasyExcel, cùng engine SAX/SXSSF. Khác biệt kiểm chứng được: vòng đời dự án, POI 5.2.5 vs 5.5.1, các API mới (numRows, csv(), headerMergeStrategy) và độ bền với file xấu — không phải hiệu năng gấp nhiều lần.

23 thg 9, 20268 phút1