Ваш метод Controller никогда не вызывается, потому что при разборе тела JSON возникло исключение.
Ваш @ContollerAdvice не применяется, поскольку метод Controller не вызывается.
Ваш метод handleIOException не вызывается, и ваш статус 422. не применяется.
Я подозреваю, что это ситуация более подробно ...
HTTP-запрос включает тело json.
Метод контроллера, соответствующий @RequestMapping и другим аннотациям запроса, принимает в качестве параметра экземпляр класса DTO.
Spring пытается десериализовать входящее тело json до вызова вашего метода управления. Это должно сделать это для передачи объекта DTO.
Десериализация использует ваш собственный десериализатор, который генерирует IOException.
Это IOException происходит до вашего метода контроллера. Фактически, ваш метод контроллера никогда не вызывается для этого запроса.
Spring обрабатывает исключение, используя его поведение по умолчанию, возвращая HTTP 400. Spring имеет очень широкую концепцию HTTP 400 RFC 7231.
Поскольку ваш метод контроллера никогда не вызывается, @ControllerAdvice никогда не применяется, и ваш @ExceptionHandler не видит исключения. Статус не установлен на 422.
Почему я верю в это?
Я часто вижу такое поведение из Spring, и я думаю, что это ожидаемое поведение. Но я не отслеживал документацию и не читал источник, чтобы быть уверенным.
Что вы можете с этим поделать?
Простой подход, который вам может не понравиться, заключается в объявлении метода вашего контроллера для приема входных данных, которые почти никогда не дают сбой, таких как String.
Вы берете на себя ответственность за проверку и десериализацию входных данных, и вы решаете, какой статус и сообщения возвращать.
Вы звоните Джексону для десериализации. Используются ваши методы @ExceptionHandler.
Бонус: Вы можете вернуть текст часто полезных сообщений об ошибках синтаксического анализа Джексона. Они могут помочь клиентам понять, почему их JSON отклонен.
Я не удивлюсь, если Spring предложит более стильный подход, класс для подкласса, специальную аннотацию. Я этого не преследовал.
Что с этим делать?
400 против 422 - дело, которое я предпочитаю не судить. В зависимости от ваших приоритетов может быть лучше принять конвенцию Спринга.
RFC 7231 On Status 400
Код состояния 400 (неверный запрос) указывает, что сервер не может или
не будет обрабатывать запрос из-за того, что воспринимается как
ошибка клиента (например, синтаксис некорректного запроса, неверный запрос)
фрейминг сообщений или обманчивая маршрутизация запросов).
Если полиция получит от вас код состояния HTTP, вы можете указать на это и сказать: « Я воспринимаю этот ввод как ошибку клиента. » Затем утверждайте, что 422 неуместно, если вы просто не обслуживаете WebDAV. чтобы вывести их из равновесия.