在Spring RestClient出错时,有没有办法记录完整的请求和响应?
我已经在这项任务上卡了相当长的时间。看起来很简单:每当RestClient请求发生错误时,我希望记录请求和响应的数据,以及它们的主体,供调试之用。
然而,RestClient似乎只能记录请求数据。对于非HTTP错误的情况,例如JSON反序列化不匹配,响应体似乎不会出现在日志中,尽管响应体已成功接收,只是格式出乎意料。
现在,我有很多通过RestClient发出的请求,收到的响应是一个字符串,然后手动将其解析为JSON,再自行处理错误。这个做法越来越让人头疼。
是否有办法在同一个位置同时捕获HTTP错误和JSON解析/反序列化错误,并在使用RestClient时记录完整的请求和响应?
同样的问题似乎也同样适用于WebClient,因为据我所知,它也缺乏对正文解析/反序列化错误的恰当处理程序。
注意:我并不想记录所有请求和响应——只有发生错误时的那些。
解决方案
在Copilot的帮助下。你需要对响应进行缓冲,这样就可以读取两遍。
public class ErrorOnlyLoggingInterceptor implements ClientHttpRequestInterceptor {
private static final Logger log = LoggerFactory.getLogger(ErrorOnlyLoggingInterceptor.class);
@Override
public ClientHttpResponse intercept(
HttpRequest request,
byte[] body,
ClientHttpRequestExecution execution) throws IOException {
ClientHttpResponse response = null;
try {
response = execution.execute(request, body);
// Wrap so we can read body safely
ClientHttpResponse wrapped =
new BufferingClientHttpResponseWrapper(response);
// Only log on error status
if (wrapped.getStatusCode().isError()) {
String requestBody = new String(body, StandardCharsets.UTF_8);
String responseBody = new String(
wrapped.getBody().readAllBytes(),
StandardCharsets.UTF_8
);
log.error("""
HTTP call failed
URI: {}
Method: {}
Status: {}
Request Body: {}
Response Body: {}
""",
request.getURI(),
request.getMethod(),
wrapped.getStatusCode(),
requestBody,
responseBody
);
}
return wrapped;
} catch (Exception ex) {
// Also log transport errors (timeouts, DNS, etc.)
log.error("""
HTTP call threw exception
URI: {}
Method: {}
Request Body: {}
Exception: {}
""",
request.getURI(),
request.getMethod(),
new String(body, StandardCharsets.UTF_8),
ex.getMessage(),
ex
);
throw ex;
}
}
}
然后把它集成到你的RestClient中(假设Spring 4)
RestClient client = RestClient.builder()
.requestFactory(
new BufferingClientHttpRequestFactory(
new SimpleClientHttpRequestFactory()
)
)
.requestInterceptor(new LoggingInterceptor())
.build();
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。