Обработка исключений в Spring Boot REST сервисе

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Для эффективного управления исключениями в REST-сервисе Spring Boot целесообразно использовать композицию аннотаций @RestControllerAdvice и @ExceptionHandler. Это позволяет контролировать ошибки на разнообразных уровнях. В качестве примера может служить следующий код:

Java
Скопировать код
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleException(Exception e) {
        String errorUUID = logErrorToNoSql(e);
        return ResponseEntity
                .status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body("К сожалению, произошла ошибка. Обратитесь с этим идентификатором: " + errorUUID);
    }

    private String logErrorToNoSql(Exception e) {
        // Здесь мы логируем информацию об ошибке с использованием NoSQL и UUID
        return UUID.randomUUID().toString();
    }
}

Такой метод обработает любое исключение, возвращая HTTP-статус 500 и идентификатор для отслеживания проблемы. Заметим, что этот метод можно адаптировать под более конкретные типы исключений.

Кинга Идем в IT: пошаговый план для смены профессии

Усовершенствуем ответы API на ошибки с помощью ResponseEntityExceptionHandler

Наследование от класса ResponseEntityExceptionHandler оптимизирует структуру ответов на исключения в API и обеспечивает единообразие в их обработке:

Java
Скопировать код
@ControllerAdvice
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {

    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(
            MethodArgumentNotValidException ex, HttpHeaders headers,
            HttpStatus status, WebRequest request) {
        ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, "Ошибка валидации данных", ex.getBindingResult().toString());
        return new ResponseEntity<>(apiError, headers, status);
    }

    // ApiError — ваш собственный класс по передаче информации об ошибке
}

Не просто 404 – Кастомные ответы на 404

Для настройки обработки NoHandlerFoundException в Spring Boot установите параметр spring.mvc.throw-exception-if-no-handler-found=true в файле application.properties. В вашем классе-советнике можно добавить следующий обработчик:

Java
Скопировать код
@ExceptionHandler(NoHandlerFoundException.class)
public ResponseEntity<Object> handleNoHandlerFoundException(NoHandlerFoundException ex, WebRequest request) {
    ApiError apiError = new ApiError(HttpStatus.NOT_FOUND, "Ой, похоже, такой страницы здесь нет.", ex.getMessage());
    return new ResponseEntity<>(apiError, new HttpHeaders(), apiError.getStatus());
}

Когда жизнь бросает вызов, перехватываем их с помощью аспектов

Для конвертации ошибок в исключения обратите внимание на аспектно-ориентированный подход:

Java
Скопировать код
@Aspect
@Component
public class ErrorHandlingAspect {

    @Around("execution(* com.yourcompany.*.*(..))")
    public Object handleErrors(ProceedingJoinPoint joinPoint) throws Throwable {
        try {
            return joinPoint.proceed();
        } catch (Error error) {
            throw new CustomException("Извините, произошла ошибка. Теперь это исключение под нашим контролем.", error);
        }
    }
}

Использование аспектов требует осторожности, чтобы не внести их поддержку там, где это не целесообразно.

Ловушки, которые следует избегать на пути обработки исключений

Избегайте использования аннотации @EnableWebMvc, которая прекращает работу автоконфигурации Spring Boot. Вместо этого опирайтесь на @ComponentScan и @EnableAutoConfiguration, чтобы воспользоваться преимуществами Spring Boot. Отключение автоматического маппинга статических ресурсов может ускорить работу чистого REST-сервиса.

Тестирование, раз, два, три... с MockMvc!

Для проверки обработки исключений используйте модульные тесты с MockMvc:

Java
Скопировать код
@RunWith(SpringRunner.class)
@WebMvcTest
public class ExceptionHandlerControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void whenMethodArgumentNotValid_thenBadRequest() throws Exception {
        mockMvc.perform(post("/endpoint")
                .content("{...}")
                .contentType(MediaType.APPLICATION_JSON))
                .andExpect(status().isBadRequest())
                .andExpect(jsonPath("$.error").value("Ошибка валидации данных"));
    }
}

Правильно написанные тесты помогут удостовериться, что обработка исключений работает корректно.

Визуализация

REST-сервис можно представить как завод:

  • Конечные точки 💻: Узлы процессов, выпускающие продукцию.
  • Исключения ⚠️: Непредвиденные препятствия в рабочем процессе.
  • Обработчик 🛠️: Команда технической поддержки для всех рабочих узлов.

Обработчики исключений в Spring Boot выступают в роли контроллеров качества:

  • Входящие исключения ⚡: Ошибки производства, требующие немедленного вмешательства.
  • ExceptionHandler 👮‍♀️: Обеспечение упорядоченной обработки возникающих ситуаций.

В конечном итоге, каждая проблема решается, а клиенту возвращается правильно сформированный HTTP-ответ.

Завершение

Используйте структурирование классов ошибок для создания унифицированного вида ошибок.

Научитесь определять, что лучше применять в вашем случае – автоматическое конфигурирование или нет, и не включайте лишнюю функциональность.

Применяйте аннотацию @ResponseStatus непосредственно к исключениям для явной установки HTTP-статуса, когда это возможно.

Рассмотрите возможность использования ModelAndView для отображения пользовательской страницы ошибки.

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

Избегайте излишних спецификаций в обработке исключений, стремитесь к более общему решению.

Полезные материалы

  1. Документация по Spring Boot — для тех, кто хочет глубже погрузиться в тему обработки ошибок в Spring Boot.
  2. Начало работы | Создание REST-сервисов с помощью Spring — пошаговый путь к созданию REST-сервисов в Spring.
  3. Глобальная обработка исключений с @ControllerAdvice – DZone — освоение глобальной обработки исключений в Spring Boot.
  4. Модульное тестирование контроллеров Spring MVC: REST API – Petri Kainulainen — модульные тесты – обязательный этап в разработке высококачественных REST-контроллеров.
  5. Пример использования MockMvc в Spring Boot с @WebMvcTest — MockMvc упрощает тестирование вашего REST API.
Свежие материалы