0Pricing
Java Academy · บทเรียน

การจัดการข้อยกเว้นแบบรวมศูนย์ด้วย @ControllerAdvice

รวมการจัดการข้อยกเว้นของคอนโทรลเลอร์ทั้งหมดไว้ที่เดียวด้วย @ExceptionHandler และ @ControllerAdvice

การจัดการข้อยกเว้นแบบรวมศูนย์ด้วย @ControllerAdvice เป็นบทเรียน Java Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Java Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน

ปัญหาเมื่อไม่มีการจัดการข้อยกเว้นแบบรวมศูนย์

หากไม่มีการจัดการข้อยกเว้นแบบรวมศูนย์ เมธอดของตัวควบคุมทุกเมธอดจะต้องมีบล็อกสำหรับดักจับข้อผิดพลาด การสร้างการตอบกลับข้อผิดพลาดจะซ้ำกัน และรายละเอียดข้อยกเว้นอาจรั่วไหลไปยังไคลเอ็นต์

@ControllerAdvice และ @RestControllerAdvice

@ControllerAdvice ใช้กำหนดคลาสตัวจัดการข้อยกเว้นแบบรวมศูนย์ ส่วน @RestControllerAdvice จะเพิ่ม @ResponseBody ทำให้เมธอดตัวจัดการทั้งหมดส่งคืน JSON โดยอัตโนมัติ

@RestControllerAdvice
public class GlobalExceptionHandler {
    // @ExceptionHandler methods go here
}

เมธอด @ExceptionHandler

ใส่คำอธิบายประกอบให้เมธอดด้วย @ExceptionHandler(ExceptionType.class) สปริงจะส่งข้อยกเว้นชนิดนั้นและคลาสย่อยไปยังเมธอดดังกล่าว ให้ส่งคืน ResponseEntity พร้อมสถานะที่เหมาะสม

@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity<ErrorResponse> handleNotFound(ResourceNotFoundException ex) {
    return ResponseEntity.status(HttpStatus.NOT_FOUND)
        .body(new ErrorResponse("NOT_FOUND", ex.getMessage()));
}

การจัดการข้อยกเว้นหลายชนิด

ระบุข้อยกเว้นหลายชนิดในตัวจัดการเดียว หรือใช้คลาสฐานร่วมกัน สปริงจะเลือกตัวจัดการที่เฉพาะเจาะจงที่สุดที่มีอยู่

@ExceptionHandler({IllegalArgumentException.class, IllegalStateException.class})
public ResponseEntity<ErrorResponse> handleBadRequest(RuntimeException ex) {
    return ResponseEntity.badRequest()
        .body(new ErrorResponse("BAD_REQUEST", ex.getMessage()));
}

การจัดการข้อผิดพลาดจากการตรวจสอบ

ดักจับ MethodArgumentNotValidException เพื่อดึงข้อผิดพลาดระดับฟิลด์จากเนื้อหาคำขอที่ผ่านการตรวจสอบด้วย @Valid

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String, Object>> handleValidation(MethodArgumentNotValidException ex) {
    Map<String, String> fieldErrors = new LinkedHashMap<>();
    ex.getBindingResult().getFieldErrors().forEach(e ->
        fieldErrors.put(e.getField(), e.getDefaultMessage()));
    return ResponseEntity.badRequest()
        .body(Map.of("errors", fieldErrors, "status", 400));
}

การจัดการการละเมิดข้อจำกัด

ConstraintViolationException จะถูกโยนเมื่อมีการตรวจสอบพารามิเตอร์ของเมธอดด้วย @Validated ที่ชั้นบริการ ควรจัดการข้อยกเว้นนี้แยกจากข้อผิดพลาดการตรวจสอบของเอ็มวีซี

@ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity<Map<String, String>> handleConstraint(ConstraintViolationException ex) {
    Map<String, String> errors = new LinkedHashMap<>();
    ex.getConstraintViolations().forEach(v ->
        errors.put(v.getPropertyPath().toString(), v.getMessage()));
    return ResponseEntity.badRequest().body(errors);
}

การเข้าถึง HttpServletRequest

เพิ่ม HttpServletRequest เป็นพารามิเตอร์เพื่อรับรายละเอียดคำขอ (ที่อยู่เว็บ เมธอด และส่วนหัว) สำหรับการบันทึกเหตุการณ์หรือใส่ไว้ในการตอบกลับข้อผิดพลาด

@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleAll(Exception ex, HttpServletRequest req) {
    log.error("Unhandled error on {} {}", req.getMethod(), req.getRequestURI(), ex);
    return ResponseEntity.internalServerError()
        .body(new ErrorResponse("INTERNAL_ERROR", "Unexpected error"));
}

@ResponseStatus บนคลาสข้อยกเว้น

ใส่คำอธิบายประกอบ @ResponseStatus ให้กับคลาสข้อยกเว้นแบบกำหนดเอง เพื่อกำหนดสถานะ HTTP โดยอัตโนมัติโดยไม่ต้องมีเมธอดตัวจัดการ เหมาะสำหรับกรณีตรงไปตรงมา

@ResponseStatus(HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
    public ResourceNotFoundException(String msg) { super(msg); }
}

การกำหนดขอบเขตของ @ControllerAdvice

จำกัดตัวช่วยให้ทำงานกับแพ็กเกจ คำอธิบายประกอบ หรือคลาสฐานที่ระบุ โดยใช้แอตทริบิวต์ของ @ControllerAdvice

@RestControllerAdvice(basePackages = "com.example.api")
public class ApiExceptionHandler { ... }
@RestControllerAdvice(assignableTypes = {UserController.class, OrderController.class})
public class SpecificHandler { ... }

การบันทึกเหตุการณ์ในตัวจัดการข้อยกเว้น

บันทึกข้อยกเว้นในระดับที่เหมาะสม: ข้อผิดพลาดจากผู้ใช้ (4xx) ที่ระดับ WARN และข้อผิดพลาดที่ไม่คาดคิด (5xx) ที่ระดับ ERROR พร้อมร่องรอยสแตกทั้งหมด

@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleAll(Exception ex, HttpServletRequest req) {
    if (ex instanceof BusinessException) log.warn("Business error: {}", ex.getMessage());
    else log.error("Unexpected error on {}", req.getRequestURI(), ex);
    return ...
}

ลำดับความสำคัญของตัวจัดการข้อยกเว้น

Spring จะเลือกตัวจัดการที่เฉพาะเจาะจงที่สุด หาก ResourceNotFoundException extends RuntimeException ตัวจัดการสำหรับ ResourceNotFoundException จะมีลำดับความสำคัญเหนือตัวจัดการสำหรับ RuntimeException

ตรวจสอบอย่างรวดเร็ว

คำอธิบายประกอบใดใช้กำกับเมธอดเพื่อจัดการข้อยกเว้นประเภทใดประเภทหนึ่งทั่วทั้งระบบ

สรุป

ใช้ @RestControllerAdvice ร่วมกับ @ExceptionHandler เพื่อรวมการจัดการข้อผิดพลาดไว้ที่เดียว ส่งคืน ResponseEntity ที่มีโครงสร้างข้อผิดพลาดสอดคล้องกัน จัดการการตรวจสอบความถูกต้อง (MethodArgumentNotValidException) และข้อจำกัด (ConstraintViolationException) แยกจากกัน บันทึก 4xx เป็น WARN และ 5xx เป็น ERROR

คำถามที่พบบ่อย

บทเรียน “การจัดการข้อยกเว้นแบบรวมศูนย์ด้วย @ControllerAdvice” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การจัดการข้อยกเว้นแบบรวมศูนย์ด้วย @ControllerAdvice” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Java Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Java Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การจัดการข้อยกเว้นแบบรวมศูนย์ด้วย @ControllerAdvice”

รวมการจัดการข้อยกเว้นของคอนโทรลเลอร์ทั้งหมดไว้ที่เดียวด้วย @ExceptionHandler และ @ControllerAdvice คุณปฏิบัติ Java Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Java Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Java Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน

บทเรียน “การจัดการข้อยกเว้นแบบรวมศูนย์ด้วย @ControllerAdvice” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Java Academy นี้ได้ไหม

ได้ บทเรียน Java Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การตรวจสอบ Bean: @NotNull, @Size, @Pattern
  2. คำอธิบายข้อจำกัดแบบกำหนดเอง
  3. การจัดการข้อยกเว้นแบบรวมศูนย์ด้วย @ControllerAdvice
  4. รายละเอียดปัญหา RFC 7807 และการตอบกลับข้อผิดพลาดอย่างสอดคล้อง
← กลับไปที่ Java Academy