เปิด problemdetails แล้วได้อะไร และไม่ได้อะไร
บทที่แล้วจบที่ปัญหาสองข้อ · body ไม่บอกว่าช่องไหนผิด และคำขอที่ผิดกับระบบที่พังจริงมีรูปเดียวกันเป๊ะ
สิ่งแรกที่คนส่วนใหญ่ทำต่อจากตรงนี้ คือเปิดสวิตช์ที่ Spring Boot เตรียมไว้ให้
สวิตช์บรรทัดเดียว
หัวข้อที่มีชื่อว่า “สวิตช์บรรทัดเดียว”มันเปลี่ยน body ข้อผิดพลาดทั้งระบบ โดยไม่ต้องแก้ตัวจัดการสักตัว
spring.mvc.problemdetails.enabled=trueเปิดแล้วยิงคำขอที่ผิดสามช่องเดิมเข้าไปใหม่
{"detail":"Invalid request content.","instance":"/bookings","status":400,"title":"Bad Request"}เทียบกับของเดิมทีละช่อง
| ก่อนเปิด | หลังเปิด | |
|---|---|---|
| รหัส | 400 | 400 |
| content-type | application/json | application/problem+json |
| ชื่อคีย์ | error path status timestamp | detail instance status title |
| บอกไหมว่าช่องไหนผิด | ไม่ | ยังไม่ |
สิ่งที่เปลี่ยนจริง คือรูป ไม่ใช่เนื้อหา
หัวข้อที่มีชื่อว่า “สิ่งที่เปลี่ยนจริง คือรูป ไม่ใช่เนื้อหา”รูปที่เปลี่ยนไปมีชื่อ และมีเอกสารมาตรฐานรองรับ
Problem DetailsProblem Details (RFC 9457)รูปมาตรฐานของ body ที่บอกความผิดพลาด · มีคีย์ `type` `title` `status` `detail` `instance` และเติมคีย์ของตัวเองได้ · เป็นรูป ไม่ใช่เนื้อหา คือรูปที่ RFC 9457 กำหนดไว้สำหรับ body ที่บอกความผิดพลาด · มันบอกว่าคีย์ไหนแปลว่าอะไร และเปิดให้เติมคีย์ของตัวเองเข้าไปได้
content-type ที่เปลี่ยนเป็น application/problem+json ไม่ใช่เรื่องเล็ก
· มันบอกตัวเรียกฝั่งผู้เรียกว่า body ก้อนนี้อ่านตามมาตรฐานได้ ไม่ต้องเดารูปเอง
RFC 9457 ระบุคีย์ type title status detail instance
· ที่วัดได้มีสี่คีย์ เพราะ type มีค่าตั้งต้นเป็น about:blank และ Spring ไม่ส่งคีย์
ที่ยังเป็นค่าตั้งต้นออกมา
สิ่งที่ไม่ปรากฏใน body ไม่ได้แปลว่าไม่มีอยู่ในมาตรฐาน · แต่ผู้เรียกที่อ่าน body
อย่างเดียวก็ไม่มีทางรู้ข้อนี้ ซึ่งเป็นเหตุผลที่ content-type สำคัญ
แล้วสิ่งที่ไม่เปลี่ยนล่ะ
หัวข้อที่มีชื่อว่า “แล้วสิ่งที่ไม่เปลี่ยนล่ะ”คีย์
detailมีค่าว่าInvalid request content.ทุกครั้ง ไม่ว่าจะผิดกี่ช่อง
คำขอของเราผิดสามช่องพร้อมกัน และระบบตรวจเจอครบทั้งสามช่อง · สิ่งที่ออกไปคือประโยคเดียวที่ไม่มีชื่อช่องอยู่ในนั้นเลย
ลองเปลี่ยนให้ผิดช่องเดียวแล้วยิงใหม่ · detail ยังเป็นประโยคเดิม
สวิตช์นี้เปลี่ยนซองจดหมาย ไม่ได้เปลี่ยนข้อความข้างใน · ผู้เรียกยังทำอะไรต่อไม่ได้ เท่าเดิมกับตอนก่อนเปิด
ข้อที่หนักกว่านั้น — มันไม่ได้ครอบทุกอย่าง
หัวข้อที่มีชื่อว่า “ข้อที่หนักกว่านั้น — มันไม่ได้ครอบทุกอย่าง”ยิงคำขอที่จองทับเวลากับใบที่มีอยู่แล้ว แล้วดูว่าอะไรออกมา
คอร์สก่อนพิสูจน์ไว้แล้วว่าฐานข้อมูลกันจองซ้อนได้จริง · ยิงใบแรกผ่าน แล้วยิงใบที่สอง ที่เวลาทับกัน
{"error":"Internal Server Error","path":"/bookings","status":500,"timestamp":"..."}สี่คีย์แบบเดิม · application/json แบบเดิม · เหมือนกับตอนที่ยังไม่ได้เปิดสวิตช์เลย
เหตุผลอยู่ที่ขอบเขตของสวิตช์เอง · มันเปลี่ยนรูปให้เฉพาะ exception ที่ Spring MVC
รู้จักและจัดการเองอยู่แล้ว เช่นตัวที่เกิดจาก @Valid
ความล้มเหลวใบที่สองไม่ใช่ตัวนั้น · มันมาจากฐานข้อมูล และตกไปที่ตัวจัดการค่าตั้งต้น ซึ่งไม่รู้จักรูปใหม่
หลังเปิดสวิตช์ ระบบของเราตอบ application/problem+json บ้าง application/json บ้าง
ขึ้นอยู่กับว่าอะไรพัง
ผู้เรียกที่เขียนตัวอ่านตามรูปใหม่จะเจอ body ที่ไม่มีคีย์ที่มันรออยู่ · การแก้ครึ่งเดียว สร้างขอบที่คาดเดายากกว่าเดิม และนี่คือเหตุผลที่บทที่ 3 กับ 4 ต้องมี
สรุปสิ่งที่วัดได้ในบทนี้
หัวข้อที่มีชื่อว่า “สรุปสิ่งที่วัดได้ในบทนี้”สามข้อ · หนึ่งข้อดีขึ้น หนึ่งข้อเท่าเดิม หนึ่งข้อไม่ถูกแตะเลย
- content-type เปลี่ยนจริง เป็น
application/problem+jsonและชื่อคีย์เปลี่ยนทั้งชุด - ข้อความยังไม่บอกว่าช่องไหนผิด
detailเป็นประโยคเดียวกันทุกครั้ง - ความขัดแย้งของข้อมูลยังเป็น 500 พร้อมสี่คีย์แบบเดิม เพราะอยู่นอกขอบเขตของสวิตช์
ProblemDetailProblemDetailชนิดใน Spring ที่แทนรูปข้างบน · คืนมันจากตัวจัดการแล้ว Spring ตั้งรหัสตอบกลับตาม `status` ของมัน และตั้ง content-type เป็น `application/problem+json` ให้เอง คือชนิดที่เราจะใช้เขียนคำตอบเองในบทถัดไป · สวิตช์เปิดรูปให้แล้ว แต่เนื้อหาต้องมีคนใส่
บทที่ 3 จะเขียนตัวจัดการตัวแรก แล้วเจอเรื่องที่ไม่มีใครเตือนเลย
- ทรงเดียวกับบทที่ 1 ทุกอย่าง ต่างกันที่บรรทัดเดียวใน
application.properties· ทรงที่ใช้วัดเป็นส่วนหนึ่งของข้ออ้าง เปลี่ยนอย่างอื่นด้วยแล้วเทียบกันไม่ได้ - Spring Boot 4.1.1 · Kotlin 2.4.10 · JDK 25 · PostgreSQL 18
- รันซ้ำเองได้ด้วย
npm run verify:clinic-http - RFC 9457 — Problem Details for HTTP APIs
(เข้าถึง 2026-09-02) — ชื่อคีย์ทั้งห้าและค่าตั้งต้นของ
type - Spring Framework — Error Responses
(เข้าถึง 2026-09-02) — ขอบเขตของ
spring.mvc.problemdetails.enabled
เช็กความเข้าใจ — บทที่ 2
ข้อ 1 / 3เปิด spring.mvc.problemdetails.enabled แล้ว อะไรเปลี่ยนจริง