0Pricing
Java Academy · Lekcja

Globalna obsługa wyjątków za pomocą @ControllerAdvice

Proszę scentralizować obsługę wyjątków we wszystkich kontrolerach za pomocą @ExceptionHandler i @ControllerAdvice.

Globalna obsługa wyjątków za pomocą @ControllerAdvice to bezpłatna lekcja Java Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Java Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Java Academy zawiera 4 lekcji w sumie.

Problem bez globalnej obsługi

Bez globalnej obsługi wyjątków każda metoda kontrolera musi zawierać bloki try-catch, tworzenie odpowiedzi błędów jest powielane, a szczegóły wyjątków mogą wyciekać do klientów.

@ControllerAdvice i @RestControllerAdvice

@ControllerAdvice definiuje globalną klasę obsługi wyjątków. @RestControllerAdvice dodaje @ResponseBody, dzięki czemu wszystkie metody obsługi automatycznie zwracają JSON.

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

Metody @ExceptionHandler

Metodę należy oznaczyć adnotacją @ExceptionHandler(ExceptionType.class). Spring przekierowuje do niej wyjątki danego typu i jego podtypów. Metoda powinna zwracać ResponseEntity z odpowiednim statusem.

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

Obsługa wielu typów wyjątków

W jednym module obsługi można wymienić wiele typów wyjątków albo użyć wspólnej klasy bazowej. Spring wybiera najbardziej szczegółowy dostępny moduł obsługi.

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

Obsługa błędów walidacji

Należy przechwycić MethodArgumentNotValidException, aby wyodrębnić błędy poszczególnych pól z treści żądań zwalidowanych za pomocą @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));
}

Obsługa naruszeń ograniczeń

ConstraintViolationException jest zgłaszany podczas walidowania parametrów metod za pomocą @Validated w warstwie usług. Należy obsługiwać go osobno od błędów walidacji MVC.

@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);
}

Dostęp do HttpServletRequest

Należy dodać HttpServletRequest jako parametr, aby uzyskać szczegóły żądania (adres URL, metodę i nagłówki) na potrzeby logowania lub uwzględnienia ich w odpowiedzi błędu.

@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 na klasach wyjątków

Niestandardowe klasy wyjątków można oznaczyć adnotacją @ResponseStatus, aby automatycznie ustawiać status HTTP bez metody obsługi — jest to prostsze rozwiązanie w nieskomplikowanych przypadkach.

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

Ograniczanie zakresu @ControllerAdvice

Zakres porady można ograniczyć do określonych pakietów, adnotacji lub klas bazowych za pomocą atrybutów adnotacji @ControllerAdvice.

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

Logowanie w modułach obsługi wyjątków

Wyjątki należy logować na odpowiednim poziomie: błędy użytkownika (4xx) na poziomie WARN, a nieoczekiwane błędy (5xx) na poziomie ERROR wraz z pełnym śladem stosu.

@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 ...
}

Priorytet procedur obsługi wyjątków

Spring wybiera procedurę obsługi najbardziej szczegółowego typu. Jeśli ResourceNotFoundException extends RuntimeException, procedura obsługi dla ResourceNotFoundException ma pierwszeństwo przed procedurą dla RuntimeException.

Szybkie sprawdzenie

Która adnotacja oznacza metodę obsługującą globalnie określony typ wyjątku?

Podsumowanie

Używaj @RestControllerAdvice + @ExceptionHandler, aby scentralizować obsługę błędów. Zwracaj ResponseEntity ze spójną strukturą błędu. Obsługuj walidację (MethodArgumentNotValidException) i ograniczenia (ConstraintViolationException) osobno. Rejestruj błędy 4xx na poziomie WARN, a błędy 5xx na poziomie ERROR.

Często zadawane pytania

Czy lekcja „Globalna obsługa wyjątków za pomocą @ControllerAdvice” jest bezpłatna?

Tak — pełny tekst „Globalna obsługa wyjątków za pomocą @ControllerAdvice” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Java Academy, przejdź na CoddyKit PRO. Kurs Java Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Globalna obsługa wyjątków za pomocą @ControllerAdvice”?

Proszę scentralizować obsługę wyjątków we wszystkich kontrolerach za pomocą @ExceptionHandler i @ControllerAdvice. Ćwiczysz Java Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Java Academy?

Nie wymagamy żadnego doświadczenia. Java Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „Globalna obsługa wyjątków za pomocą @ControllerAdvice”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Java Academy?

Tak. Każda lekcja Java Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Walidacja beanów: @NotNull, @Size, @Pattern
  2. Niestandardowe adnotacje ograniczeń
  3. Globalna obsługa wyjątków za pomocą @ControllerAdvice
  4. Szczegóły problemu RFC 7807 i spójne odpowiedzi błędów
← Powrót do Java Academy