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 21: REST CRUD: POST, PUT, DELETE và mã trạng thái
Java và Spring Boot – MVC và REST API

Spring Boot bài 21: REST CRUD: POST, PUT, DELETE và mã trạng thái

  • 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 21/28 · Biên soạn tháng 10/2026.

← Bài 20 · Mục lục 12 chương · Bài 22 →

Mục lục

  • Mục tiêu bài học
  • Tạo tài nguyên bằng POST
  • PUT cập nhật đầy đủ phần được phép sửa
  • DELETE và tính idempotent
  • Chạy một vòng CRUD có xác thực và CSRF
  • 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

Thiết kế request tạo/sửa/xóa, trả Location khi tạo mới và kiểm tra kết quả bằng một chuỗi request hoàn chỉnh.

Tạo tài nguyên bằng POST

POST /api/courses nhận JSON có title, price và categoryId. @RequestBody yêu cầu Spring đọc body thành CourseForm; @Valid kiểm tra ràng buộc trước nghiệp vụ. Khi tạo thành công, API trả 201 Created, body là DTO vừa lưu và Location trỏ tới URL chi tiết.

Không cho client tùy chọn id khi tạo mới trong hợp đồng này. Id đến từ database. Location giúp client biết tài nguyên vừa được tạo ở đâu mà không phải tự suy đoán quy tắc URL. Ở hệ thống có gateway hoặc context path phức tạp, có thể dùng công cụ xây URI theo request và cấu hình forwarded header tin cậy.

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.

@PostMapping("/courses") ResponseEntity<CourseDto> create(@Valid @RequestBody CourseForm form){CourseDto dto=service.create(form);return ResponseEntity.created(URI.create("/api/courses/"+dto.id())).body(dto);}
@PutMapping("/courses/{id}") CourseDto update(@PathVariable Long id,@Valid @RequestBody CourseForm form){return service.update(id,form);}
@DeleteMapping("/courses/{id}") ResponseEntity<Void> delete(@PathVariable Long id){service.delete(id);return ResponseEntity.noContent().build();}

PUT cập nhật đầy đủ phần được phép sửa

PUT /api/courses/{id} trong mẫu yêu cầu đủ ba trường được sửa, không phải JSON tùy ý chỉ có một trường. Nếu bỏ title hoặc categoryId, validation từ chối. Endpoint không có chức năng upsert: id không tồn tại trả 404. Hãy ghi rõ lựa chọn này trong hợp đồng để client không mặc định PUT sẽ tự tạo mới.

PATCH dành cho cập nhật một phần cần thiết kế riêng, bao gồm cách biểu diễn trường không gửi và trường muốn xóa. Không biến PUT thành PATCH một cách ngầm định bằng cách bỏ qua mọi giá trị null; điều đó làm hợp đồng khó dự đoán.

DELETE và tính idempotent

DELETE /api/courses/{id} trả 204 No Content sau khi xóa. Response 204 không cần thêm JSON thông báo. Gọi lại cùng id trong mẫu trả 404 vì tài nguyên đã mất. Idempotent nói về trạng thái đích khi thao tác lặp lại, không bắt buộc mọi lần phải trả cùng mã status.

POST tạo mới thông thường không idempotent: gửi hai lần có thể tạo hai khóa học. Với nghiệp vụ quan trọng cần chống lặp, phải có thiết kế khóa/ràng buộc/idempotency riêng. Không dựa vào việc UI khóa nút để đảm bảo chỉ có một request.

Chạy một vòng CRUD có xác thực và CSRF

Dùng quy trình lấy token và session ở bài 19, rồi POST JSON tạo khóa học. Lấy Location từ response, GET để kiểm tra, PUT toàn bộ dữ liệu mới, GET lại và cuối cùng DELETE. GET lần cuối phải trả 404. Mỗi request ghi đều cần teacher và token hợp lệ.

Nếu gặp 415, kiểm tra Content-Type và định dạng body; 400 thường là JSON/validation/tham số; 403 cần kiểm tra quyền hoặc CSRF; 404 có thể là id không tồn tại hoặc URL sai. Không sửa nghiệp vụ xóa khi request chưa qua được tầng Security. Test crudRoundTrip trong mã mẫu thực hiện chính chuỗi này trong transaction kiểm thử.

Tệp trong mã nguồn mẫu: src/test/java/com/hocvietcode/academy/ApiIntegrationTest.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.

@Test void crudRoundTrip()throws Exception{
    String location=mvc.perform(post("/api/courses").with(user("t").roles("TEACHER")).with(csrf()).contentType("application/json").content(JSON))
      .andExpect(status().isCreated()).andReturn().getResponse().getHeader("Location");
    mvc.perform(put(location).with(user("t").roles("TEACHER")).with(csrf()).contentType("application/json").content(JSON.replace("REST demo","Updated")))
      .andExpect(status().isOk()).andExpect(jsonPath("$.title").value("Updated"));
    mvc.perform(delete(location).with(user("t").roles("TEACHER")).with(csrf())).andExpect(status().isNoContent());
    mvc.perform(get(location)).andExpect(status().isNotFound());
}

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

  • Không nhận một entity có id từ client rồi save mà chưa xác định đang tạo hay cập nhật tài nguyên nào.
  • 204 không có body; đừng bắt client parse JSON sau một DELETE thành công theo hợp đồng này.

Ghi nhớ

CRUD API cần thống nhất URL, method, đầu vào, status và quyền; một chuỗi kiểm tra trọn vòng sẽ phát hiện nhiều lỗi hơn từng request riêng lẻ.

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

  • ResponseEntity

← Bài 20 · Mục lục 12 chương · Bài 22 →

Bài viết liên quan:

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
Java và Spring Boot – MVC và REST API
Spring Boot bài 27: Logging, Actuator và quản lý schema bằng Flyway
Java và Spring Boot – MVC và REST API
Spring Boot bài 11: Post/Redirect/Get, flash message và session
Java và Spring Boot – MVC và REST API
Spring Boot bài 28: Đóng gói JAR, Docker và cấu hình triển khai
Java và Spring Boot – MVC và REST API
Spring Boot bài 12: JPA Entity, Repository, H2 và migration đầu tiên
Java và Spring Boot – MVC và REST API
Giáo trình Spring Boot MVC và REST API 2026: 12 chương, 28 bài
Java và Spring Boot – MVC và REST API
Spring Boot bài 13: Kết nối MySQL, CRUD và transaction trong Service

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
×