Это будет небольшой совет, чем готовое решение, но я думаю, что решение может быть не столь очевидным.
В общем случае, если вы читаете полезную нагрузку один раз из запроса, из InputStream из HttpRequest , это может больше не быть доступным для остальной части весеннего заявления. (Spring, вероятно, делает (или может делать) прокси-объект для хранения полезной нагрузки запроса чтения из InputStream для доступа к нему несколько раз).
Я думаю, вы можете создать HTTP-фильтр и установить MDC
context после обработка HTTP-запроса - но в этом случае вы можете регистрировать сообщение об ошибке только в теле после обработки этого запроса, но не во время (когда вы регистрируете сообщения, как правило, вы не знаете, закончится ли этот запрос http 500 или нет).
Если мы говорим о Spring, у вас здесь есть класс абстрактного фильтра, который может вам помочь: org.springframework.web.filter.AbstractRequestLoggingFilter
Вот простой фильтр, созданный мной (но не проверенный) на основе источника AbstractRequestLoggingFilter
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.WebUtils;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
@Component
public class TestFilter extends OncePerRequestFilter {
private static final int MAX_PAYLOAD_LENGTH = 50_000;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
HttpServletRequest requestToUse = request;
if (!(request instanceof ContentCachingRequestWrapper)) {
requestToUse = new ContentCachingRequestWrapper(request, MAX_PAYLOAD_LENGTH);
}
try {
filterChain.doFilter(requestToUse, response);
} catch (RuntimeException | ServletException | IOException e) {
MDC.put("request-payload", convertRequestPayloadToString(request));
// You can also log your exception here
throw e;
} finally {
if (response.getStatus() != 200) {
MDC.put("request-payload", convertRequestPayloadToString(request));
}
}
}
private String convertRequestPayloadToString(HttpServletRequest request) {
ContentCachingRequestWrapper wrapper =
WebUtils.getNativeRequest(request, ContentCachingRequestWrapper.class);
StringBuilder sb = new StringBuilder();
if (wrapper != null) {
byte[] buf = wrapper.getContentAsByteArray();
if (buf.length > 0) {
int length = Math.min(buf.length, MAX_PAYLOAD_LENGTH);
String payload;
try {
payload = new String(buf, 0, length, wrapper.getCharacterEncoding());
} catch (UnsupportedEncodingException ex) {
payload = "[unknown]";
}
sb.append(payload);
}
}
return sb.toString();
}
}