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
@RestControllerCRUD đầy đủ với đúng HTTP method, status code (201/204/404), vàLocationheader - Explain cơ chế
HandlerMethodArgumentResolvercho 6 nguồn binding (path, query, body, header, cookie, attribute) và type conversion - Design exception handling tập trung qua
@RestControllerAdvice+ProblemDetailRFC 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),WebMvcConfigurerinterface, externalized config. Module 03 assume bạn biết tại sao Boot tự setupDispatcherServletmà 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ài | Chủ đề | Phút |
|---|---|---|
| 00 | Tổng quan (đang đọc) | 10 |
| 01 | DispatcherServlet — front controller + 9 infrastructure bean | 26 |
| 02 | @RestController và @RequestMapping | 22 |
| 03 | Request binding — 6 nguồn, type conversion, record DTO | 24 |
| 04 | Response handling — ResponseEntity, status code, streaming | 22 |
| 05 | Exception handling — @ControllerAdvice, Problem Details RFC 9457 | 24 |
| 06 | Validation — Jakarta Bean Validation, custom constraint | 22 |
| 07 | OpenAPI/Swagger — springdoc-openapi, Swagger UI | 22 |
| 08 | Mini-challenge: TaskFlow REST API v1 (capstone) | 35 |
| 09 | Tổng kết & cheat sheet | 15 |
| 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ả
-
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
@RestControllervới 1@GetMappingvà gọicurl localhost:8080/test. Sau bài 04, kiểm tra status code trả về có đúng là 201 không bằngcurl -v. Tay gõ thực tế nhiều hơn đọc lý thuyết. -
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óProblemDetailnative theo RFC 9457 — 1 object duy nhất, không cần class custom. Nếu thấy tutorial cũ dùngErrorResponseclass tự viết, skip ngay. -
Bài 06 (Validation) — add
spring-boot-starter-validationexplicit. Boot 3 tách validation khỏistarter-web. Nhiều dev quên add → annotation@NotBlankcó nhưng không trigger → bug ngầm. Luôn checkpom.xmlcó dependency này. -
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.htmlngay. 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. -
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?