Я использую Spring Boot 1.4.1, который включает spring -web-4.3.3. У меня есть класс, аннотированный с помощью @ControllerAdvice
и методы, аннотированные с помощью @ExceptionHandler
, для обработки исключений, переданных служебным кодом. При обработке этих исключений я хотел бы зарегистрировать @RequestBody
, который был частью запроса на операции PUT и POST, чтобы я мог видеть тело запроса, которое вызвало проблему, которая в моем случае имеет решающее значение для диагностики.
Per Spring Docs подпись метода для методов @ExceptionHandler
может включать в себя различные вещи, включая HttpServletRequest
. Тело запроса обычно может быть получено здесь через getInputStream()
или getReader()
, но если мои методы контроллера анализируют тело запроса, например "@RequestBody Foo fooBody"
, как все мое, входной поток или считыватель HttpServletRequest's
уже закрыт вызывается метод моего обработчика исключений. По существу тело запроса уже было прочитано Spring, как описано в здесь. Общей проблемой, связанной с сервлетами, является то, что тело запроса можно прочитать только один раз.
К сожалению, @RequestBody
не является одним из параметров, доступных для метода обработчика исключений, если бы тогда я мог его использовать.
Я могу добавить InputStream
к методу обработчика исключений, но это заканчивается тем же, что и HttpServletRequest InputStream, и поэтому имеет ту же проблему.
Я также попытался получить текущий запрос с ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest()
, который является еще одним трюком для получения текущего запроса, но в итоге это тот же HttpServletRequest, что Spring переходит в метод обработчика исключений и поэтому имеет ту же проблему.
Я прочитал несколько решений, таких как this и , которые включают в себя вставку специальной оболочки запроса в цепочку фильтров, которая будет считывать содержимое запроса и кэшировать их, чтобы их можно было читать более одного раза. Мне не нравится это решение, потому что я не хочу прерывать всю цепочку фильтров/запросов/ответов (и, возможно, создавать проблемы с производительностью или стабильностью), только для реализации ведения журнала, и если у меня есть большие запросы, такие как загруженные документы (которые Я), я не хочу кэшировать это в памяти. Кроме того, Spring, вероятно, имеет @RequestBody
где-то кэшированный, если бы я мог его найти.
Кстати, многие решения рекомендуют использовать класс ContentCachingRequestWrapper
Spring, но по моему опыту это не работает. Помимо того, что он не документирован, глядя на его исходный код, похоже, что он кэширует только параметры, но не тело запроса. Попытка получить тело запроса из этого класса всегда приводит к пустой строке.
Итак, я ищу любые другие варианты, которые я, возможно, пропустил. спасибо за чтение.