Основная проблема с запросом на чтение заключается в том, что, как только входной поток потребляется, он исчезает ... и не может быть прочитан снова. Поэтому входной поток должен быть кэширован. Вместо написания ваших собственных классов для кэширования (которые можно найти в нескольких местах в Интернете), Spring предоставляет несколько полезных классов, то есть ContentCachingRequestWrapper и ContentCachingResponseWrapper . Эти классы могут быть очень эффективно использованы, например, в фильтрах для целей регистрации.
Определить фильтр в web.xml:
<filter>
<filter-name>loggingFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>loggingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Поскольку фильтр объявлен как DelegatingFilterProxy, его можно объявить как компонент с помощью аннотаций @Component или @Bean. В методе doFilter loggingFilter оберните запрос и ответ классами, предоставленными пружиной, прежде чем передавать его в цепочку фильтров:
HttpServletRequest requestToCache = new ContentCachingRequestWrapper(request);
HttpServletResponse responseToCache = new ContentCachingResponseWrapper(response);
chain.doFilter(requestToCache, responseToCache);
String requestData = getRequestData(requestToCache);
String responseData = getResponseData(responseToCache);
Входной поток будет кэширован в упакованном запросе, как только входной поток будет использован после chain.doFilter (). Тогда к нему можно получить доступ, как показано ниже:
public static String getRequestData(final HttpServletRequest request) throws UnsupportedEncodingException {
String payload = null;
ContentCachingRequestWrapper wrapper = WebUtils.getNativeRequest(request, ContentCachingRequestWrapper.class);
if (wrapper != null) {
byte[] buf = wrapper.getContentAsByteArray();
if (buf.length > 0) {
payload = new String(buf, 0, buf.length, wrapper.getCharacterEncoding());
}
}
return payload;
}
Однако для ответа все немного по-другому. Поскольку ответ также был упакован перед передачей его в цепочку фильтров, он также будет кэширован в выходной поток, как только он будет записан на обратном пути. Но поскольку выходной поток также будет использован, вам придется скопировать ответ обратно в выходной поток с помощью wrapper.copyBodyToResponse (). Смотрите ниже:
public static String getResponseData(final HttpServletResponse response) throws IOException {
String payload = null;
ContentCachingResponseWrapper wrapper =
WebUtils.getNativeResponse(response, ContentCachingResponseWrapper.class);
if (wrapper != null) {
byte[] buf = wrapper.getContentAsByteArray();
if (buf.length > 0) {
payload = new String(buf, 0, buf.length, wrapper.getCharacterEncoding());
wrapper.copyBodyToResponse();
}
}
return payload;
}
Надеюсь, это поможет!