VieTopik
Tiếng HànTiếng AnhIT
  • Góc học tập
Tải app
  • Thư viện
  • Luyện thi
  • Cẩm nang
  • Góc học tập
Spring Boot Web APIXây API CRUD
Bài 4/19
5 phút

Nhận dữ liệu từ request

Nội dung bài · 5 mục
  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 5.Tóm tắt

API cần biết client muốn gì: sản phẩm số mấy, tìm theo tên nào, tạo sản phẩm với tên và giá bao nhiêu. Dữ liệu đó nằm ở ba chỗ trong request. Bài này chỉ cách nhận cả ba vào tham số của handler method.

Khái niệm

🔗 Binding tham số (argument binding): cơ chế Spring tự lấy dữ liệu trong request và gán vào tham số của handler method.

Nguồn Ví dụ trong request Annotation
Route /api/products/5 @PathVariable
Query string ?name=pen&maxPrice=10000 @RequestParam
Body (JSON) { "name": "Pen", "price": 5000 } @RequestBody

Mỗi tham số ghi rõ annotation cho biết nó lấy từ đâu. Riêng object trong body, thiếu @RequestBody thì Spring không đọc JSON vào object đó.

Ví dụ

// ProductsController.java
package com.shop.api;

import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/products")
class ProductsController {
    @GetMapping("/{id}")
    public String getById(@PathVariable int id) {
        return "Sản phẩm " + id;
    }

    @GetMapping("/search")
    public String search(
            @RequestParam String name,
            @RequestParam long maxPrice) {
        return "Tìm " + name
                + ", giá tối đa " + maxPrice;
    }

    @PostMapping
    public Product create(
            @RequestBody Product product) {
        return product;
    }
}

// Product.java
package com.shop.api;

class Product {
    private String name = "";
    private long price;

    public String getName() { return name; }
    public long getPrice() { return price; }

    public void setName(String name) {
        this.name = name;
    }

    public void setPrice(long price) {
        this.price = price;
    }
}
  • getById(@PathVariable int id): id trùng tên với {id} trong route nên lấy từ URL.
  • search(...): @RequestParam lấy name và maxPrice từ query string ?name=...&maxPrice=....
  • create(@RequestBody Product product): đọc body JSON thành object Product.
  • Spring tự đổi chuỗi trong URL thành int, long. Đổi không được thì trả lỗi 400.

Thử ngay

Giữ các file cũ, thay ProductsController.java và Product.java theo phần Ví dụ, rồi chạy lại server. Gọi hai request GET:

curl -i "http://localhost:5000/api/products/5"
curl -i "http://localhost:5000/api/products/search?name=pen&maxPrice=10000"

Để gửi POST, tạo file product.json:

{ "name": "Pen", "price": 5000 }

Rồi gửi file đó làm body:

curl -i -X POST http://localhost:5000/api/products -H "Content-Type: application/json" -d @product.json

Đoán trước khi chạy: field name của Product là private. Method create có nhận được tên sản phẩm không?

Xem kết quả
HTTP/1.1 200
Content-Type: application/json

{"name":"Pen","price":5000}

Có. Spring tạo Product bằng constructor không tham số, rồi gọi setName, setPrice theo tên trường trong JSON. Method trả lại đúng object vừa nhận.

Tên trường phải khớp cả hoa thường. JSON viết "Name" thì không có setter nào khớp, trường đó bị bỏ qua và name giữ giá trị rỗng.

Lỗi hay gặp

Gửi chữ vào tham số số. id là int mà URL lại là chữ, Spring không đổi được và trả về 400.

// SAI — "abc" không phải số, nhận về 400 Bad Request
GET /api/products/abc
// ĐÚNG
GET /api/products/5

Quên header Content-Type. Không có -H, curl gửi body với kiểu của form (application/x-www-form-urlencoded). Server không đọc kiểu này như JSON và trả về 415 Unsupported Media Type.

# SAI — thiếu -H "Content-Type: application/json"
curl -i -X POST http://localhost:5000/api/products -d @product.json
# ĐÚNG
curl -i -X POST http://localhost:5000/api/products -H "Content-Type: application/json" -d @product.json

Tóm tắt

  • Spring tự gán dữ liệu request vào tham số của handler method.
  • Dữ liệu đến từ route (@PathVariable), query string (@RequestParam) hoặc body JSON (@RequestBody).
  • Object trong body cần @RequestBody, tên trường JSON phải khớp tên getter, setter.
  • Gửi JSON phải có header Content-Type: application/json.

Tự kiểm tra

0/3 câu
Câu 1

Method có @GetMapping("/{orderId}/lines") và tham số @PathVariable int orderId, @RequestParam int page. Gọi GET /api/orders/7/lines?page=2 thì orderId và page bằng bao nhiêu?

Câu 2

Client gửi thông tin đơn hàng mới gồm nhiều trường. Dữ liệu này nên đặt ở đâu trong request?

Câu 3

POST body JSON đúng, nhưng server trả 415 Unsupported Media Type. Nguyên nhân khả dĩ nhất?

Controller và routingTrả về kết quả

Nội dung bài

  1. 1.Khái niệm
  2. 2.Ví dụ
  3. 3.Thử ngay
  4. 4.Lỗi hay gặp
  5. 5.Tóm tắt