logo

Управление исключениями в фильтрах Spring: CorsFilter, JDBC

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

Чтобы обрабатывать исключения, которые могут появиться при работе фильтра, применяйте аннотацию @ControllerAdvice в сочетании с методами @ExceptionHandler.

Java
Скопировать код
@ControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleException(Exception e) {
        // Производится обработка каждого исключения
        return new ResponseEntity<>("Упс! Что-то пошло не так.", HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

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

Создание собственного фильтра для обработки исключений

Создайте свой фильтр, который станет первой линией обороны в цепiцце фильтров и будет перехватывать исключения, прежде чем они достигнут контроллеров.

Java
Скопировать код
public class ExceptionHandlingFilter extends OncePerRequestFilter {

    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) 
            throws ServletException, IOException {
        try {
            filterChain.doFilter(request, response);
        } catch (RuntimeException e) {
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            response.setContentType(MediaType.APPLICATION_JSON_VALUE);
            ErrorResponse errorResponse = new ErrorResponse("Произошла ошибка!", e.getMessage());
            response.getWriter().write(objectMapper.writeValueAsString(errorResponse));
        }
    }
    
    public static class ErrorResponse {
        private String message;
        private String detailedMessage;

        // Геттеры и сеттеры не представлены для удобства
    }
}

Такой фильтр преобразует исключения в структурированный JSON-ответ.

Интеграция обработки исключений фильтра и контроллера

Для интеграции обработки исключений на уровне фильтра и контроллера мы используем HandlerExceptionResolver.

Java
Скопировать код
public class FilterExceptionHandler extends OncePerRequestFilter {

    @Autowired
    private HandlerExceptionResolver resolver;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) 
        throws ServletException, IOException {
        try {
            filterChain.doFilter(request, response);
        } catch (Exception e) {
            resolver.resolveException(request, response, null, e);
        }
    }
}

Благодаря этому подходу, фильтр передает обработку исключений на зону ответственности глобального обработчика @ControllerAdvice.

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

Управление исключениями в фильтрах Spring можно изобразить так, как если бы это была хорошо отлаженная городская транспортная система:

Движение (🚗) → Дороги (Фильтр) → [🚦] Авария!
Система дорог (🔗): [Дорога1(🛣️) → Дорога2(🌉) → Дорога3(🛤️)]
Место аварии (🆘): Происшествие на дороге 2 (🌉)

Роль Spring в этой модели аналогична роли полиции, контролирующей движение:

🚗 → 🛣️ → 🚦 → 🆘
# Spring управляет движением и надежно реагирует на происшествия.

Каждый инцидент обрабатывается быстро и эффективно:

Расследование происшествия: 🚔 (реакция на ситуацию)

И в оживленном городе движение продолжается без задержек:

🚗 → 🛣️ → 🌉 → 🛤️ → 🚦
                                  🚔 → 🗂️ → 💼
# Происшествие устранено, дорога свободна. Все продолжают движение.

Использование фильтров безопасности

Исключения могут возникать и при использовании Фильтров Безопасности, поэтому их также следует интегрировать в механизм обработки ошибок в Spring Security.

Java
Скопировать код
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private ExceptionHandlingFilter exceptionHandlingFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(exceptionHandlingFilter, CorsFilter.class);
        // Операции по настройке защитных механизмов...
    }
}

Эта конфигурация обеспечивает перехват и адекватную обработку всех исключений, возникающих на этапе фильтрации безопасности.

Единообразие – ключ к успеху: Стандартная структура ответа о ошибке

Единообразие в обработке и отображении ошибок упрощает их обработку. Вот пример стандартной структуры для сообщений об ошибках:

Java
Скопировать код
public class StandardErrorResponse {

    private int status;
    private String message;
    private long timestamp;

    // Конструкторы, геттеры и сеттеры не представлены для удобства
}

ObjectMapper представляет клиенту ответ в формате JSON, обеспечивая однообразие в общении с сервером.

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

  1. Документация по Spring Boot — Подробное руководство по обработке ошибок в Spring Boot.
  2. Обработка исключений в Spring MVC — DigitalOcean — Обзор обработки исключений в Spring MVC.
  3. Как начать работу со созданием REST-сервисов на Spring — Пошаговый гид по созданию REST-сервисов.
  4. DZone: Расширенные возможности по обработке исключений в Spring — Продвинутые техники обработки ошибок в Spring.
  5. StackOverflow: Лучшие практики форматирования сообщений об ошибках REST в Spring MVC — Обмен опытом и наилучшими практиками среди сообщества разработчиков.