hocvietcode.com
  • Trang chủ
  • Học lập trình
    • Lập trình C/C++
    • Cấu trúc dữ liệu và giải thuật
    • Lập trình HTML
    • Lập trình Javascript
      • Javascript cơ bản
      • ReactJS framework
      • AngularJS framework
      • Typescript cơ bản
      • Angular
      • NodeJS
    • Lập trình Mobile
      • Lập Trình Dart Cơ Bản
        • Dart Flutter Framework
    • Cơ sở dữ liệu
      • MySQL – MariaDB
      • Micrsoft SQL Server
      • Extensible Markup Language (XML)
      • JSON
      • MongoDB
    • Lập trình PHP
      • Lập trình PHP cơ bản
      • Laravel Framework
    • Lập trình Java
      • Java Cơ bản
      • Spring Boot
    • Lập trình C#
      • Lập Trình C# Cơ Bản
      • ASP.NET Core MVC
    • Machine Learning
    • Git và Github
  • WORDPRESS
    • WordPress cơ bản
    • WordPress nâng cao
    • Chia sẻ WordPress
  • Kiến thức hệ thống
    • Microsoft Azure
    • Docker
    • Linux
  • Chia sẻ IT
    • Tin học văn phòng
      • Microsoft Word
      • Microsoft Excel
    • Marketing
      • Google Adwords
      • Facebook Ads
      • Kiến thức khác
    • Chia sẻ phần mềm
    • Review công nghệ
    • Công cụ – tiện ích
      • Kiểm tra bàn phím online
      • Kiểm tra webcam online
  • Lập trình Python
Đăng nhập
  • Đăng nhập / Đăng ký

Please enter key search to display results.

Home
  • Spring Boot
Spring Boot bài 20: REST Controller, JSON và DTO cho API danh sách
Java và Spring Boot – MVC và REST API

Spring Boot bài 20: REST Controller, JSON và DTO cho API danh sách

  • 18-10-2026
  • Toanngo92
  • 0 Comments

Giáo trình Spring Boot MVC và REST API · Chương 9/12: REST API và hợp đồng HTTP · Bài 20/28 · Biên soạn tháng 10/2026.

← Bài 19 · Mục lục 12 chương · Bài 21 →

Mục lục

  • Mục tiêu bài học
  • Cùng nghiệp vụ, khác cách trả kết quả
  • DTO là hợp đồng dữ liệu
  • Cấu trúc phân trang dễ dùng cho client
  • Content negotiation và cách đọc lỗi
  • Lỗi thường gặp và lưu ý
  • Ghi nhớ
  • Tài liệu đối chiếu

Mục tiêu bài học

Tạo endpoint đọc dữ liệu bằng JSON, dùng DTO và envelope phân trang ổn định thay vì trả entity trực tiếp.

Cùng nghiệp vụ, khác cách trả kết quả

CourseWebController trả tên template; CourseApiController dùng @RestController để kết quả được ghi vào response body qua message converter. Hai Controller gọi cùng CourseService, nên không có hai phiên bản quy tắc cập nhật khóa học. @RequestMapping("/api") tạo tiền tố chung cho nhóm endpoint.

GET /api/courses trả danh sách có phân trang. GET /api/courses/{id} trả một khóa học. Đây là các thao tác đọc công khai theo bảng quyền của mẫu. HTTP method mang ý nghĩa: GET cần không tạo thay đổi nghiệp vụ như thêm dòng hoặc gửi email.

Tệp trong mã nguồn mẫu: src/main/java/com/hocvietcode/academy/CourseApiController.java. Đoạn dưới được trích từ tệp này; xem bản tải về để có đủ import và phần còn lại.

@RestController @RequestMapping("/api")
public class CourseApiController {
    private final CourseService service;
    public CourseApiController(CourseService service){this.service=service;}
    @GetMapping("/courses") PageDto<CourseDto> list(@RequestParam(defaultValue="") String q,@RequestParam(defaultValue="0") int page,@RequestParam(defaultValue="10") int size,@RequestParam(defaultValue="id") String sort){return PageDto.from(service.search(q,page,size,sort));}
    @GetMapping("/courses/{id}") CourseDto get(@PathVariable Long id){return service.get(id);}

DTO là hợp đồng dữ liệu

CourseDto gồm id, title, price, categoryId và categoryName. JSON không chứa đối tượng Category với toàn bộ thuộc tính hoặc proxy Hibernate. Việc tách entity và DTO giúp thay đổi schema nội bộ mà không nhất thiết thay hợp đồng công khai.

Request tạo/sửa dùng CourseForm có validation. Response dùng CourseDto có id do server cấp. Dù tên CourseForm gợi giao diện HTML, nó hiện là đối tượng đầu vào dùng chung có phạm vi nhỏ; khi web và API có quy tắc khác nhau, hãy tách request DTO thay vì ép hai luồng dùng một cấu trúc không còn phù hợp.

Tệp trong mã nguồn mẫu: src/main/java/com/hocvietcode/academy/PageDto.java. Đoạn dưới được trích từ tệp này; xem bản tải về để có đủ import và phần còn lại.

package com.hocvietcode.academy;
import java.util.List;
import org.springframework.data.domain.Page;
public record PageDto<T>(List<T> content,int page,int size,long totalElements,int totalPages) {
    public static <T> PageDto<T> from(Page<T> p){return new PageDto<>(p.getContent(),p.getNumber(),p.getSize(),p.getTotalElements(),p.getTotalPages());}
}

Cấu trúc phân trang dễ dùng cho client

PageDto chủ động trả năm trường: content, page, size, totalElements, totalPages. Client không cần biết PageImpl của Spring Data có thêm những thuộc tính nội bộ nào. page vẫn bắt đầu từ 0 như trong endpoint HTML, còn giao diện người dùng có thể hiển thị số trang từ 1.

Thử GET /api/courses?size=1&q=Spring&sort=title bằng trình duyệt hoặc công cụ HTTP. Kết quả phải có mảng content và thông tin tổng. Khi không có bản ghi phù hợp, một danh sách rỗng với 200 là hợp lý; điều đó khác với GET một id không tồn tại trả 404.

curl -i "http://localhost:8080/api/courses?size=1&q=Spring&sort=title"
curl -i "http://localhost:8080/api/courses/1"

Content negotiation và cách đọc lỗi

Client nên gửi Accept: application/json khi muốn JSON. POST JSON cần Content-Type: application/json để server biết cách đọc body; Accept và Content-Type không cùng vai trò. Mã status cho biết kết quả tổng quát, còn body bổ sung dữ liệu hoặc chi tiết lỗi.

Không bọc mọi kết quả trong HTTP 200 rồi nhét success=false vào JSON, vì client, cache và công cụ giám sát sẽ mất tín hiệu chuẩn. Ở bài tiếp theo, 201, 204, 400 và 404 được dùng theo từng thao tác. API cũng không tự trở nên bảo mật chỉ vì URL có tiền tố /api.

Lỗi thường gặp và lưu ý

  • Không trả JpaRepository hoặc entity lazy ra response và để serializer quyết định hợp đồng.
  • GET danh sách rỗng là trường hợp bình thường, không cần 404.

Ghi nhớ

REST Controller chuyển kết quả nghiệp vụ thành HTTP/JSON; DTO giữ cấu trúc response rõ ràng và có thể kiểm thử.

Tài liệu đối chiếu

  • ResponseBody

← Bài 19 · Mục lục 12 chương · Bài 21 →

Bài viết liên quan:

Java và Spring Boot – MVC và REST API
Spring Boot bài 17: Spring Security: đăng nhập, mật khẩu và SecurityFilterChain
Java và Spring Boot – MVC và REST API
Spring Boot bài 18: Phân quyền teacher/student và bảo vệ endpoint
Java và Spring Boot – MVC và REST API
Spring Boot bài 19: CSRF, CORS và gọi API có session đúng cách
Java và Spring Boot – MVC và REST API
Spring Boot bài 21: REST CRUD: POST, PUT, DELETE và mã trạng thái
Java và Spring Boot – MVC và REST API
Spring Boot bài 22: Validation API, ProblemDetail và hợp đồng lỗi
Java và Spring Boot – MVC và REST API
Spring Boot bài 23: Gọi dịch vụ HTTP bằng RestClient và đặt timeout
Java và Spring Boot – MVC và REST API
Spring Boot bài 24: Gửi email và lập lịch tác vụ trong Spring Boot
Java và Spring Boot – MVC và REST API
Spring Boot bài 08: Fragment, layout và tài nguyên CSS trong Spring Boot
Java và Spring Boot – MVC và REST API
Spring Boot bài 25: Unit test Service với JUnit và Mockito
Java và Spring Boot – MVC và REST API
Spring Boot bài 09: Binding biểu mẫu tạo và sửa khóa học
Java và Spring Boot – MVC và REST API
Spring Boot bài 26: Integration test MVC, API, database và Security
Java và Spring Boot – MVC và REST API
Spring Boot bài 10: Validation và BindingResult: báo lỗi ngay trên biểu mẫu

Dịch vụ thiết kế Wesbite

NỘI DUNG MỚI CẬP NHẬT

Giáo trình Python: mục lục 12 chương, 24 bài từ cơ bản đến ứng dụng

Python bài 24: Lock, Queue và thiết kế worker an toàn

Python bài 23: Thread, start, join và concurrency

Python bài 22: Kết nối MySQL và CRUD có transaction

Python bài 21: Gọi HTTP API, xử lý JSON và tải dữ liệu

Giới thiệu

hocvietcode.com là website chia sẻ và cập nhật tin tức công nghệ, chia sẻ kiến thức, kỹ năng. Chúng tôi rất cảm ơn và mong muốn nhận được nhiều phản hồi để có thể phục vụ quý bạn đọc tốt hơn !

Liên hệ quảng cáo: [email protected]

Kết nối với HỌC VIẾT CODE

© hocvietcode.com - Tech888 Co .Ltd since 2019

Đăng nhập

Trở thành một phần của cộng đồng của chúng tôi!
Registration complete. Please check your email.
Đăng nhập bằng google
Đăng kýBạn quên mật khẩu?

Create an account

Welcome! Register for an account
The user name or email address is not correct.
Registration confirmation will be emailed to you.
Log in Lost your password?

Reset password

Recover your password
Password reset email has been sent.
The email could not be sent. Possible reason: your host may have disabled the mail function.
A password will be e-mailed to you.
Log in Register
×