Я регистрирую тело запроса, если возникает какое-то пользовательское исключение. Для этого я добавил фильтр, который кэширует объект HttpServletRequest с помощью ContentCachingRequestWrapper. Вот пример кода для этого:
@Component
public class RequestWrapperFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {
filterChain.doFilter(new ContentCachingRequestWrapper(httpServletRequest), httpServletResponse);
}
}
@PostMapping(Paths.INSPECTION_IMAGE_SUBMIT_REQUEST_V1)
public ResponseEntity<ResponseObject> processThisRequest(
@RequestBody RequestObject requestObject //how am I able to access this requestObject?
) throws Exception {
return someService.process(requestBody);
}
Итак, как я могу использовать это requestObject? Так как в классе фильтра я закэшировал это, значит, метод getReader() уже должен был быть вызван для этого, верно? Значит, я не смогу прочитать requestObject, верно?




Попробуйте это решение . Пока вы передаете объект wrapRequest (как указано в этой ссылке) вперед для цепочки фильтров, вы можете прочитать requestObject в своем контроллере.
====== РЕДАКТИРОВАТЬ ======
Посмотрите, как работает ContentCachingRequestWrapper
Оболочка javax.servlet.http.HttpServletRequest, которая кэширует весь контент, прочитанный из входного потока и считывателя, и позволяет извлекать этот контент через массив байтов.
Кэширование не означает, что он читает входной поток и сохраняет его в памяти, но всякий раз, когда байты считываются из обернутого потока, кешировщик будет записывать те же байты в свой внутренний буфер.
Таким образом, ваш requestObject читается только один раз во всей цепочке фильтров, когда вы создаете ContentCachingRequestWrapper в своем фильтре, он еще ничего не кэширует.
Другая часть фреймворка будет считывать кешированный контент, вызывая метод ContentCachingRequestWrapper#getContentAsByteArray (не считывать из потока повторно, так как он уже прочитан). (Обратите внимание, что контент доступен только после того, как средство чтения тела закончит чтение входного потока, если вы вызовете его раньше, вы получите неполные данные)
======КОНЕЦ РЕДАКТИРОВАНИЯ======
Можно использовать RequestBodyAdviceAdapter
@ControllerAdvice
public class RequestAdvice extends RequestBodyAdviceAdapter {
@Override
@Nonnull
public Object afterBodyRead(@Nonnull Object body, @Nonnull HttpInputMessage inputMessage,
@Nonnull MethodParameter parameter, @Nonnull Type targetType,
@Nonnull Class<? extends HttpMessageConverter<?>> converterType) {
// Do something with the payload
return super.afterBodyRead(body, inputMessage, parameter, targetType, converterType);
}
}
Привет @Mạnh Quyết Nguyễn. Спасибо за ответ, но я хочу понять, как работает мой текущий код. Разве контроллер не должен генерировать исключение, поскольку я уже прочитал тело запроса в кеше содержимого?
В ссылке на решение, размещенной выше, должна возникнуть та же проблема, т. Е. Тело запроса должно быть нулевым, потому что оно уже прочитано кэшированием контекста в фильтре? Я сомневаюсь, как работает мое решение, поскольку я уже прочитал тело запроса в кэшировании контента до того, как оно достигнет моего контроллера?