Spring Boot/Module 03 — REST API với Spring MVC: tổng quan
~10 phútREST API với Spring MVCMiễn phí lượt xem

Module 03 — REST API với Spring MVC: tổng quan

Học gì, vì sao học, học xong làm được gì. DispatcherServlet front-controller, @RestController routing, request/response binding, exception handling RFC 9457, validation, OpenAPI — nền tảng REST API production-grade.

TL;DR: Module 03 bóc tầng Web Layer của Spring Boot — từ DispatcherServlet nhận mọi HTTP request qua 9 bước front-controller, @RestController routing annotation-driven, 6 nguồn binding (path/query/body/header/cookie/attribute), ResponseEntity với status code đúng ngữ nghĩa (201 Created/204 No Content/304 Not Modified), đến exception handling tập trung theo Problem Details RFC 9457, Jakarta Bean Validation 23 constraint declarative, và OpenAPI 3.x doc tự động qua springdoc-openapi. Capstone TaskFlow v1 là REST API CRUD đầu tiên bạn build từ scratch — baseline cho Module 04 (JPA), 05 (Security), và các module tiếp theo.

Vì sao module này tồn tại

Thứ Hai tuần trước, team nhận ticket: "API /api/orders/42 trả 500 nhưng không có log nào rõ ràng. Client frontend báo 'Unknown error'. Khách hàng mất đơn hàng."

Bạn mở log production. Thấy dòng: java.lang.NullPointerException: null. Không có stack trace — ai đó đã dùng log.error("failed: " + e.getMessage()). Không có request ID để trace xuyên layer. Response body trả về là HTML Tomcat error page thay JSON.

Sau 3 giờ debug: nguyên nhân là @RequestBody không có @Valid — field total null, service gọi total.compareTo(ZERO) → NullPointerException. Fix là 1 annotation @NotNull. Nhưng 3 giờ mất vì không có:

  • Validation fail-fast → không đến service.
  • Problem Details response → client biết field nào sai.
  • Correlation ID → trace request end-to-end.

Module 03 xây đúng những thứ đó. Sau module, bạn có REST API layer hoạt động như production từ ngày đầu — không phải retrofit sau khi đã có bug.

Một ví dụ khác: nhiều dev Spring Boot khi cần document API vẫn viết tay Confluence — luôn outdated vì code đổi nhưng doc quên update. springdoc-openapi 1 dependency, không cần config, tự sinh Swagger UI tại /swagger-ui.html với full schema từ annotation đã có sẵn. Frontend dev có interactive doc để test ngay. Không cần đợi bạn viết doc.

Sau module này bạn sẽ

  • Trace vòng đời 1 HTTP request qua 9 bước DispatcherServlet — từ Tomcat nhận request đến MessageConverter write JSON response
  • Implement @RestController CRUD đầy đủ với đúng HTTP method, status code (201/204/404), và Location header
  • Explain cơ chế HandlerMethodArgumentResolver cho 6 nguồn binding (path, query, body, header, cookie, attribute) và type conversion
  • Design exception handling tập trung qua @RestControllerAdvice + ProblemDetail RFC 9457 — không leak stack trace production
  • Implement Jakarta Bean Validation với 23 built-in constraint, custom @Constraint, cross-field validation, và validation groups
  • Design và expose OpenAPI 3.x doc qua springdoc-openapi: customize @Operation/@Schema, security scheme, và workflow API-first cho TaskFlow API

Lộ trình module

Bài 01 đặt nền tảng infrastructure: DispatcherServlet là Front Controller duy nhất nhận mọi request. Bạn theo dõi 9 bước từ Tomcat dispatch → HandlerMapping tìm method → HandlerAdapter invoke → HttpMessageConverter serialize JSON. 9 bean infrastructure (HandlerMapping, HandlerAdapter, HandlerInterceptor, MessageConverter, ViewResolver, MultipartResolver, HandlerExceptionResolver, LocaleResolver, ThemeResolver) phối hợp ra sao — và WebMvcAutoConfiguration setup tất cả tự động như thế nào. Sau bài này, "request không đến controller" không còn là mystery — bạn biết debug bước 2-5.

Bài 02 bóc annotation-driven controller: vì sao @RestController = @Controller + @ResponseBody, 3 generation evolution từ XML (2003) đến annotation (2026). @RequestMapping 7 attribute + 5 shortcut annotation, PathPattern syntax Spring 6+, content negotiation qua produces/consumes, và 3 strategy API versioning (path/header/media type). Richardson Maturity Model — vì sao 99% "REST API" production là Level 2 pragmatic, không phải Level 3 HATEOAS strict.

Bài 03 bóc binding: HandlerMethodArgumentResolver mechanism cho 6 nguồn (path/query/body/header/cookie/attribute), type conversion String → Long/UUID/Enum/Date, record DTO với @Valid cascade. Pattern thực tế: filter object, pagination với Pageable, PUT vs PATCH semantic và JSON Patch RFC 6902.

Bài 04 là mirror của bài 03: ResponseEntity builder, HTTP status code ngữ nghĩa (200/201/202/204/304/4xx/5xx), custom header (Location, ETag, X-Total-Count), file download StreamingResponseBody, SSE SseEmitter, ResponseBodyAdvice cho global wrap. Sau bài này, bạn không bao giờ trả 200 cho mọi case.

Bài 05 là quan trọng nhất module cho production: @RestControllerAdvice + ProblemDetail RFC 9457 (Boot 3 native). 3 layer exception handling, domain exception → HTTP status mapping, security (không leak stack trace), testing exception handler với MockMvc. Pattern: 1 GlobalExceptionHandler xử lý mọi exception toàn app.

Bài 06 đào sâu Jakarta Bean Validation: 23 built-in constraint, @Valid cascade, custom @Constraint annotation, cross-field validation qua @AssertTrue/class-level, validation groups (Create/Update), validation trong service layer. spring-boot-starter-validation — tách khỏi starter-web từ Boot 3, phải add explicit.

Bài 07 bóc OpenAPI/Swagger: springdoc-openapi auto-generate spec từ annotation, Swagger UI /swagger-ui.html, customize @Operation/@ApiResponse/@Schema, security scheme (JWT Bearer), group multi-API, pattern API-first vs code-first. 1 dependency → full interactive API doc cho frontend team.

Bài 08 mini-challenge capstone TaskFlow v1: build REST API CRUD đầy đủ từ scratch — domain Project + Task, 8 endpoint, validation, Problem Details, OpenAPI doc, in-memory storage. Baseline sẽ extend qua các module 04-15.

Bài 09 tổng kết: cheat sheet, glossary, pitfall code sai/đúng, self-assessment 6 outcomes.

Yêu cầu trước khi bắt đầu

  • Spring Core (Module 01): hiểu IoC container, bean lifecycle, ApplicationContext.refresh(), BeanPostProcessor. DispatcherServlet là 1 Spring bean — hiểu bean lifecycle giải thích cách nó được register.
  • Spring Boot Foundations (Module 02): hiểu auto-configuration (WebMvcAutoConfiguration, DispatcherServletAutoConfiguration), WebMvcConfigurer interface, externalized config. Module 03 assume bạn biết tại sao Boot tự setup DispatcherServlet mà không cần config.
  • HTTP fundamentals: biết HTTP method (GET/POST/PUT/DELETE), status code class (2xx/4xx/5xx), header (Content-Type, Authorization), body (JSON). Bài 01 có section ôn nhanh nhưng nếu chưa biết gì, đọc MDN HTTP Guide trước.
  • Java 17+ records: cú pháp record Foo(String bar) {} — dùng nhiều trong DTO pattern.
  • Maven + JDK 21: spring-boot-starter-web + spring-boot-starter-validation + springdoc-openapi-starter-webmvc-ui.

Time budget

BàiChủ đềPhút
00Tổng quan (đang đọc)10
01DispatcherServlet — front controller + 9 infrastructure bean26
02@RestController và @RequestMapping22
03Request binding — 6 nguồn, type conversion, record DTO24
04Response handling — ResponseEntity, status code, streaming22
05Exception handling — @ControllerAdvice, Problem Details RFC 945724
06Validation — Jakarta Bean Validation, custom constraint22
07OpenAPI/Swagger — springdoc-openapi, Swagger UI22
08Mini-challenge: TaskFlow REST API v1 (capstone)35
09Tổng kết & cheat sheet15
Tổng~3.7h đọc + 0.5h lab + buffer

Khuyến nghị: chia làm 3 ngồi:

  • Ngồi 1 (~1.5h): bài 00 → 02 (orient + DispatcherServlet infrastructure + controller annotation).
  • Ngồi 2 (~1.5h): bài 03 → 05 (binding + response + exception handling — 3 bài cốt lõi production).
  • Ngồi 3 (~1.5h): bài 06 (validation) + bài 07 (OpenAPI) + bài 08 (lab). Lab cần 1 ngồi liên tục — đừng ngắt giữa.

Cách học module này hiệu quả

  1. Test mỗi endpoint bằng curl hoặc HTTPie ngay khi viết. Đừng chờ bài 08 lab. Sau khi đọc bài 02, tạo 1 @RestController với 1 @GetMapping và gọi curl localhost:8080/test. Sau bài 04, kiểm tra status code trả về có đúng là 201 không bằng curl -v. Tay gõ thực tế nhiều hơn đọc lý thuyết.

  2. Bài 05 (Problem Details) — đừng dùng pattern Spring 4 cũ. Pattern cũ là trả Map<String, Object> hoặc @ResponseBody ErrorDto. Boot 3 có ProblemDetail native theo RFC 9457 — 1 object duy nhất, không cần class custom. Nếu thấy tutorial cũ dùng ErrorResponse class tự viết, skip ngay.

  3. Bài 06 (Validation) — add spring-boot-starter-validation explicit. Boot 3 tách validation khỏi starter-web. Nhiều dev quên add → annotation @NotBlank có nhưng không trigger → bug ngầm. Luôn check pom.xml có dependency này.

  4. Bài 07 (OpenAPI) — mở Swagger UI cho frontend team xem. Sau khi add springdoc-openapi-starter-webmvc-ui, mở http://localhost:8080/swagger-ui.html ngay. Cho frontend dev thấy — họ có thể test endpoint trực tiếp trong UI mà không cần hỏi bạn. Đây là lý do thực sự của bài này.

  5. Bài 08 lab — không xem solution trước 30 phút. 8 endpoint CRUD TaskFlow là template bạn sẽ lặp lại trong mọi module tiếp theo. Tự build từ đầu lần này → nhớ mãi. Stuck? Tra bài 01-07 — mọi pattern đều đã cover.

Bài này có giúp bạn hiểu bản chất không?