DEV Community

Cover image for Исключения в Spring: как приручить свои ошибки
Olga Lugacheva
Olga Lugacheva

Posted on

Исключения в Spring: как приручить свои ошибки

Итак, вы внедряете Spring в свой проект, и тут, как по закону Мерфи, появляется исключение. Но не спешите паниковать — Spring обладает мощными возможностями для обработки ошибок! Давайте разберемся, как именно вы можете использовать эти возможности.

Checked и Unchecked исключения: почему всё так запутано?

Проверяемые и непроверяемые перекрестки

Java делит исключения на два типа: checked (проверяемые) и unchecked (непроверяемые). Checked исключения требуют явной обработки.Представьте два пешеходных перехода, через которые проходят люди. Один переход охраняется строгим инспектором с табличкой "Строгий контроль". Здесь проверяют каждого человека, и, если у него нет разрешения на проход, его не пропустят. Этот переход — аналог checked исключений: они требуют обязательной обработки, иначе программа не скомпилируется.

Второй переход, напротив, не контролируется. Люди проходят через него свободно и быстро, без каких-либо проверок. Это аналог unchecked исключений: такие исключения не требуют обработки, и код можно запустить даже без проверок на ошибки. Однако в случае ошибки она проявится неожиданно — прямо на «дороге».

public void someMethod() throws IOException { 
    throw new IOException("Oops, checked exception!");
}

Enter fullscreen mode Exit fullscreen mode

@ExceptionHandler: когда ошибки получают VIP-обслуживание

@ExceptionHandler — это ваш собственный персональный "вышибала", который ловит и обрабатывает исключения только для указанных методов или классов. Если хотите дать VIP-обслуживание определенным ошибкам, аннотируйте метод с @ExceptionHandler и наслаждайтесь.

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<String> handleResourceNotFound(ResourceNotFoundException ex) {
        return new ResponseEntity<>("Resource not found: " + ex.getMessage(), HttpStatus.NOT_FOUND);
    }

Enter fullscreen mode Exit fullscreen mode

Теперь при каждой встрече с ResourceNotFoundException, ваш обработчик спокойно выведет дружелюбное сообщение вместо того, чтобы пользователь увидел страшный стек ошибок.

@ControllerAdvice: когда нужно раздавать советы налево и направо

Если @ExceptionHandler работает только для конкретного класса, то @ControllerAdvice — это король массового обслуживания. Эта аннотация охватывает все контроллеры, так что ошибки больше не ускользнут!

Exception Handler

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleGlobalException(Exception ex) {
        return new ResponseEntity<>("Oops, something went wrong!", HttpStatus.INTERNAL_SERVER_ERROR);
    }
}
Enter fullscreen mode Exit fullscreen mode

С таким кодом все непойманные ошибки будут перехвачены и обработаны с единым сообщением. Это как настройка "Все включено" для исключений — удобно и безопасно.

@ResponseStatus: когда хотите сделать исключение более выразительным

Иногда стандартные статусы HTTP не совсем отражают суть исключения. Но с помощью @ResponseStatus вы можете заставить исключения быть более выразительными.

ResponseStatus

@ResponseStatus(HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
    public ResourceNotFoundException(String message) {
        super(message);
    }
}
Enter fullscreen mode Exit fullscreen mode

Теперь при выбросе ResourceNotFoundException Spring автоматически вернет статус 404, не заставляя вас делать это вручную. Отличный способ добавить драматичности, не так ли?

@RestControllerAdvice: для любителей REST

@RestControllerAdvice — это как @ControllerAdvice, но исключительно для REST-контроллеров. То есть, это ваш лучшайший выбор для создания API, так как он возвращает JSON вместо HTML-страниц. Поддержка для настоящих фанатов REST!

RestControllerAdvice

@RestControllerAdvice
public class RestExceptionHandler {

    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseEntity<String> handleIllegalArgument(IllegalArgumentException ex) {
        return new ResponseEntity<>("Illegal argument provided: " + ex.getMessage(), HttpStatus.BAD_REQUEST);
    }
}
Enter fullscreen mode Exit fullscreen mode

Такой подход гарантирует, что ваши пользователи всегда получат структурированные ответы в формате JSON, что делает ваши API ещё более дружелюбными.

Кастомные исключения: когда стандартных не хватает

Кастомное исключение

В какой-то момент вы понимаете, что стандартные Exception и RuntimeException просто не выражают всей трагедии вашей ситуации. Что ж, создавайте свои собственные исключения! Кастомные исключения добавляют немного индивидуальности, а Spring всё равно обрабатывает их с уважением.

public class InsufficientFundsException extends RuntimeException {
    public InsufficientFundsException(String message) {
        super(message);
    }
}

Enter fullscreen mode Exit fullscreen mode

Создайте для него обработчик, и пользователи вашего приложения увидят понятное сообщение, а не набор пугающих строчек.

Заключение
Обработка ошибок в Spring — это своего рода искусство. От обработки на уровне метода до глобальной обработки, от JSON-ответов до кастомных статусов — возможности действительно обширны.

Так что берите в руки @ExceptionHandler, @ControllerAdvice, и @ResponseStatus, и превращайте исключения в настоящий мастер-класс управления ошибками. Spring готов помочь вам справиться с любой ошибкой и сохранить лицо перед пользователями

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay