Что такое контроллер эдвайс в Spring и для чего он нужен
Что проверяют
Умеете ли вы централизовать то, что иначе расползается по всем контроллерам: обработку исключений, формат ошибки, общие атрибуты модели. По ответу видно, представляете ли вы, где в цепочке обработки запроса этот механизм ещё работает, а где уже нет.
Как отвечать
Класс с аннотацией ControllerAdvice это бин, чьи методы применяются сразу ко всем контроллерам. В нём живут три вида методов: обработчики ExceptionHandler, подготовка модели через ModelAttribute и настройка связывания через InitBinder. Вариант RestControllerAdvice добавляет ResponseBody, то есть возвращённое значение сразу идёт в тело ответа.
@RestControllerAdvice
class ApiErrors {
@ExceptionHandler(ResourceNotFoundException.class)
ProblemDetail notFound(ResourceNotFoundException e) {
return ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, e.getMessage());
}
}Область действия сужается параметрами аннотации: по пакетам, по аннотации контроллера, по базовому типу. Так у публичного API и у внутреннего может быть разный формат ошибки. Порядок между несколькими такими классами задают через Order, а среди обработчиков выигрывает ближайший по иерархии исключения.
Смысл в том, что контроллеры перестают знать про коды ответов чужих слоёв: трансляция доменных исключений в статусы описана в одном месте, формат ошибки один на всё приложение.
Где спотыкаются
Ставят обработчик на Exception и радуются единому ответу. Вместе с прикладными ошибками он проглатывает служебные исключения диспетчера, и несуществующий путь или неверный метод начинают отдавать код 500.
Ждут, что сюда долетят исключения из фильтров сервлета и из механизма безопасности. Всё, что упало до диспетчера, проходит мимо, там нужен свой обработчик точки входа или страница ошибки.
Отдают наружу сообщение исходного исключения. В теле ответа оказываются имена таблиц и текст запроса, а клиент так и не получает ни стабильного кода ошибки, ни понятного описания.