Я пытаюсь настроить крупномасштабный сервер служб REST. Мы используем Spring Boot 1.2.1 Spring 4.1.5 и Java 8. Наши контроллеры реализуют @RestController и стандартные аннотации @RequestMapping.
Моя проблема в том, что Spring Boot устанавливает перенаправление по умолчанию для исключений контроллера /error
. Из документов:
Spring Boot обеспечивает отображение / error по умолчанию, которое обрабатывает все ошибки разумным способом, и оно регистрируется как «глобальная» страница ошибок в контейнере сервлета.
Начиная с многолетнего написания REST-приложений на Node.js, для меня это не очень разумно. Любое исключение, которое генерирует конечная точка службы, должно возвращаться в ответе. Я не могу понять, почему вы отправляете перенаправление тем, кто, скорее всего, является пользователем Angular или JQuery SPA, который только ищет ответ и не может или не будет предпринимать никаких действий по перенаправлению.
Я хочу настроить глобальный обработчик ошибок, который может принимать любое исключение - либо намеренно выбрасывать из метода сопоставления запросов, либо автоматически генерировать Spring (404, если не найден метод обработчика для сигнатуры пути запроса), и возвращать стандартный отформатированный ответ об ошибке (400, 500, 503, 404) клиенту без каких-либо перенаправлений MVC. В частности, мы собираемся принять ошибку, зарегистрировать ее в NoSQL с UUID, а затем вернуть клиенту правильный код ошибки HTTP с UUID записи журнала в теле JSON.
Документы были расплывчаты о том, как это сделать. Мне кажется, что вы должны либо создать свою собственную реализацию ErrorController, либо каким- либо образом использовать ControllerAdvice , но все примеры, которые я видел, по-прежнему включают пересылку ответа на какое-то отображение ошибок, которое не помогает. Другие примеры предполагают, что вам нужно будет перечислить все типы исключений, которые вы хотите обработать, вместо того, чтобы просто перечислять «Throwable» и получать все.
Может кто-нибудь сказать мне, что я пропустил, или указать мне правильное направление, как это сделать, не предлагая цепочку, с которой было бы легче иметь дело с Node.js?
источник
Ответы:
Новый ответ (2016-04-20)
Использование Spring Boot 1.3.1.RELEASE
Новый шаг 1. Легко и менее навязчиво добавить следующие свойства в application.properties:
При работе с полным RESTful-приложением очень важно отключить автоматическое сопоставление статических ресурсов, поскольку, если вы используете конфигурацию Spring Boot для обработки статических ресурсов, обработчик ресурсов будет обрабатывать запрос (он упорядочен последним и сопоставлен с / ** это означает, что он принимает любые запросы, которые не были обработаны каким-либо другим обработчиком в приложении), поэтому у сервлета-диспетчера нет возможности вызвать исключение.
Новый ответ (2015-12-04)
Использование Spring Boot 1.2.7.RELEASE
Новый шаг 1 - я нашел гораздо менее навязчивый способ установки флага "throExceptionIfNoHandlerFound". Замените приведенный ниже код замены DispatcherServlet (Шаг 1) следующим образом в классе инициализации вашего приложения:
В этом случае мы устанавливаем флаг в существующем DispatcherServlet, который сохраняет любую автоконфигурацию средой Spring Boot.
Еще одна вещь, которую я нашел - аннотация @EnableWebMvc смертельно опасна для Spring Boot. Да, эта аннотация позволяет, например, перехватывать все исключения контроллера, как описано ниже, но также убивает МНОГО полезной автоматической конфигурации, которую обычно обеспечивает Spring Boot. Используйте эту аннотацию с особой осторожностью при использовании Spring Boot.
Оригинальный ответ:
После долгих исследований и отслеживания решений, опубликованных здесь (спасибо за помощь!) И немалого количества трассировки времени выполнения в коде Spring, я наконец нашел конфигурацию, которая будет обрабатывать все исключения (не ошибки, а чтение) в том числе 404 с.
Шаг 1 - скажите SpringBoot прекратить использование MVC для ситуаций «обработчик не найден». Мы хотим, чтобы Spring генерировал исключение, а не возвращал клиенту перенаправление представления на «/ error». Для этого вам нужно иметь запись в одном из ваших классов конфигурации:
Недостатком этого является то, что он заменяет сервлет диспетчера по умолчанию. Для нас это еще не проблема, без каких-либо побочных эффектов или проблем с выполнением. Если вы собираетесь делать что-то еще с сервлетом-диспетчером по другим причинам, это место для них.
Шаг 2 - Теперь, когда весенняя загрузка выдает исключение, когда обработчик не найден, это исключение может быть обработано с любыми другими в унифицированном обработчике исключений:
Имейте в виду, что я думаю, что аннотация "@EnableWebMvc" здесь важна. Кажется, что ничего из этого не работает без него. И все - ваше загрузочное приложение Spring теперь будет перехватывать все исключения, включая 404, в вышеприведенном классе обработчиков, и вы можете делать с ними, как вам угодно.
И последнее замечание - похоже, нет способа заставить его ловить ошибочные ошибки. У меня есть дурацкая идея использовать аспекты для отлова ошибок и превращения их в исключения, с которыми может справиться приведенный выше код, но у меня еще не было времени, чтобы на самом деле попытаться реализовать это. Надеюсь, это кому-нибудь поможет.
Любые комментарии / исправления / улучшения будут оценены.
источник
@ExceptionHandler
метода, вызываемого при помещении его в@ControllerAdvice
класс, хотя они правильно работают, если помещены в@RestController
класс.@EnableWebMvc
находится на@ControllerAdvice
и@Configuration
(я проверял каждую комбинацию) класс. Любая идея или рабочий пример? // @ Энди УилкинсонВ Spring Boot 1.4+ были добавлены новые классные классы для облегчения обработки исключений, которые помогают удалить шаблонный код.
Для
@RestControllerAdvice
обработки исключений предусмотрено новое , это комбинация@ControllerAdvice
и@ResponseBody
. Вы можете удалить метод@ResponseBody
on@ExceptionHandler
при использовании этой новой аннотации.т.е.
Для обработки 404 ошибок достаточно добавить
@EnableWebMvc
аннотацию и следующее в application.properties:spring.mvc.throw-exception-if-no-handler-found=true
Вы можете найти и поиграть с источниками здесь:
https://github.com/magiccrafter/spring-boot-exception-handling
источник
@RestControllerAdvice
без дополнительной настройки. Что мне здесь не хватает?Я думаю,
ResponseEntityExceptionHandler
отвечает вашим требованиям. Пример кода для HTTP 400:Вы можете проверить этот пост
источник
HttpRequestMethodNotSupportedException
и добавления одного и того же баночка в несколько микро-сервисов, для некоторых бизнес-целей нам нужно ответить псевдонимом микро-сервиса в ответе. Есть ли способ получить основное имя микро-службы / имя контроллера? Я знаюHandlerMethod
, предоставит имя метода Java, из которого происходит исключение. Но здесь ни один из методов не получил запрос, поэтомуHandlerMethod
не будет инициализирован. Так есть ли решение, чтобы решить эту проблему?Хотя это более старый вопрос, я хотел бы поделиться своими мыслями по этому поводу. Я надеюсь, что это будет полезно для некоторых из вас.
В настоящее время я создаю REST API, который использует Spring Boot 1.5.2.RELEASE с Spring Framework 4.3.7.RELEASE. Я использую подход Java Config (в отличие от конфигурации XML). Кроме того, мой проект использует глобальный механизм обработки исключений с использованием
@RestControllerAdvice
аннотации (см. Ниже).У моего проекта те же требования, что и у вас: я хочу, чтобы мой REST API возвращал a
HTTP 404 Not Found
с полезной нагрузкой JSON в ответе HTTP клиенту API, когда он пытается отправить запрос на несуществующий URL-адрес. В моем случае полезная нагрузка JSON выглядит следующим образом (что явно отличается от Spring Boot по умолчанию, кстати):Я наконец заставил это работать. Вот основные задачи, которые вы должны сделать вкратце:
NoHandlerFoundException
выбрасывается, если клиенты API вызывают URLS, для которых не существует метода-обработчика (см. Шаг 1 ниже).ApiError
), который содержит все данные, которые должны быть возвращены клиенту API (см. Шаг 2).NoHandlerFoundException
и возвращает правильное сообщение об ошибке клиенту API (см. Шаг 3).Хорошо, теперь к деталям:
Шаг 1. Настройте application.properties
Мне пришлось добавить следующие два параметра конфигурации в
application.properties
файл проекта :Это гарантирует, что
NoHandlerFoundException
он генерируется в тех случаях, когда клиент пытается получить доступ к URL-адресу, для которого не существует метода контроллера, который мог бы обработать запрос.Шаг 2. Создание класса для ошибок API
Я сделал класс, похожий на предложенный в этой статье в блоге Евгения Параскива. Этот класс представляет ошибку API. Эта информация отправляется клиенту в теле ответа HTTP в случае ошибки.
Шаг 3. Создание / настройка глобального обработчика исключений
Я использую следующий класс для обработки исключений (для простоты я удалил операторы импорта, регистрационный код и некоторые другие, не относящиеся к делу части кода):
Шаг 4: Написать тест
Я хочу убедиться, что API всегда возвращает правильные сообщения об ошибках вызывающему клиенту, даже в случае сбоя. Таким образом, я написал такой тест:
@ActiveProfiles("dev")
Аннотации можно оставить далеко. Я использую его только потому, что работаю с разными профилями. ЭтоRegexMatcher
пользовательский сопоставитель Hamcrest, который я использую для лучшей обработки полей меток времени. Вот код (я нашел его здесь ):Некоторые дополнительные заметки с моей стороны:
@EnableWebMvc
аннотацию. Это не было необходимо в моем случае.источник
Как насчет этого кода? Я использую аварийное отображение запросов, чтобы поймать 404 ошибки.
источник
По умолчанию Spring Boot выдает json с подробной информацией об ошибке.
Это также работает для всех видов ошибок отображения запросов. Проверьте эту статью http://www.jayway.com/2014/10/19/spring-boot-error-responses/
Если вы хотите создать, войдите в NoSQL. Вы можете создать @ControllerAdvice, где вы будете регистрировать его, а затем повторно выдать исключение. В документации есть пример https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc
источник
@RestControllerAdvice - это новая функция Spring Framework 4.3 для обработки исключений с помощью RestfulApi с помощью комплексного решения проблемы:
источник
Для контроллеров REST я бы рекомендовал использовать
Zalando Problem Spring Web
.https://github.com/zalando/problem-spring-web
Если Spring Boot стремится внедрить некоторую автоконфигурацию, эта библиотека делает больше для обработки исключений. Вам просто нужно добавить зависимость:
А затем определите одну или несколько советов для ваших исключений (или используйте те, которые предусмотрены по умолчанию)
Затем вы можете определить совет контроллера для обработки исключений следующим образом:
источник
Для людей, которые хотят отвечать в соответствии с кодом статуса http, вы можете использовать
ErrorController
способ:ResponseBean
Вот мой заказ POJO для ответа.источник
Решение с
dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
и@EnableWebMvc @ControllerAdvice
работал для меня с Spring Boot 1.3.1, пока не работал на 1.2.7источник