下面是从 Spring 的 AsyncRestTemplate
执行异步休息调用时记录请求和响应的拦截器代码。
如果我们可以在其他包中使用 BufferingClientHttpResponseWrapper ,则此代码可以正常工作。
Here有关 BufferingClientHttpResponseWrapper 以及如何使用 AsyncRestTemplate 添加它的一些详细信息。
我的问题是当我在 AsyncRestTemplate 中使用 HttpComponentsAsyncClientHttpRequestFactory 时。我如何获得缓冲响应。我们不能使用 BufferingClientHttpResponseWrapper ,如下所示,因为它不是公共(public)类。还有其他方法吗?
我知道 HttpComponent AsyncHttpClient 有可用的线路日志。但它将拥有整个应用程序中所有 AsyncResttemplates 的所有日志。如果我们只想捕获一个模板的日志,那么我认为 Interceptor 是唯一的方法。请建议是否有其他可用选项。
public class AsyncRestReqResInterceptor implements AsyncClientHttpRequestInterceptor {
private static final XLogger REQ_RES_LOGGER = XLoggerFactory.getXLogger("myLogger");
@Override
public ListenableFuture<ClientHttpResponse> intercept(HttpRequest request, byte[] body, AsyncClientHttpRequestExecution execution) throws IOException {
String requestPath = request.getURI().getPath();
REQ_RES_LOGGER.debug(request.getMethod()+" "+requestPath);
String requestBody = new String(body);
REQ_RES_LOGGER.debug(requestBody);
ListenableFuture<ClientHttpResponse> listenableFuture = execution.executeAsync(request, body);
ListenableFutureAdapter<ClientHttpResponse,ClientHttpResponse> futureAdapter=
new ListenableFutureAdapter<ClientHttpResponse, ClientHttpResponse>(listenableFuture) {
@Override
protected ClientHttpResponse adapt(ClientHttpResponse adapteeResult) throws ExecutionException {
return logResponseBody(adapteeResult);
}
};
return futureAdapter;
}
private ClientHttpResponse logResponseBody(ClientHttpResponse response,boolean isImageInResponse){
try {
BufferingClientHttpResponseWrapper responseWrapper = new BufferingClientHttpResponseWrapper(response);
REQ_RES_LOGGER.debug("Response Status Code :" + responseWrapper.getStatusCode().value());
REQ_RES_LOGGER.debug("Response Status Text :" + responseWrapper.getStatusText());
if (response != null && response.getBody() != null) {
String responseXml = IOUtils.toString(responseWrapper.getBody(), Charset.defaultCharset());
REQ_RES_LOGGER.debug(responseXml);
} else {
REQ_RES_LOGGER.debug("Empty Response Body");
}
return responseWrapper;
}catch (IOException io){
REQ_RES_LOGGER.error("Unexpected Error ",io);
return response;
}
}
}
最佳答案
我终于找到了使用这个类的方法。由于这是一个最终类,因此只能在 Springframework 中使用。有一个pull request在 springframework 中进行此更改。我不确定此更改何时会合并到框架中,但下面是解决上述问题的类。如果我们想拦截日志记录的请求和响应,这些类将会很有帮助。
BufferingAsyncClientHttpRequestFactory
public class BufferingAsyncClientHttpRequestFactory extends
BufferingClientHttpRequestFactory
implements AsyncClientHttpRequestFactory {
private final AsyncClientHttpRequestFactory requestFactory;
/**
* Create a buffering wrapper for the given {@link ClientHttpRequestFactory}.
* @param requestFactory the target request factory to wrap
*/
public BufferingAsyncClientHttpRequestFactory(AsyncClientHttpRequestFactory requestFactory) {
super((ClientHttpRequestFactory) requestFactory);
this.requestFactory=requestFactory;
}
/**
* Indicates whether the request/response exchange for the given URI and method
* should be buffered in memory.
* <p>The default implementation returns {@code true} for all URIs and methods.
* Subclasses can override this method to change this behavior.
* @param uri the URI
* @param httpMethod the method
* @return {@code true} if the exchange should be buffered; {@code false} otherwise
*/
@Override
public AsyncClientHttpRequest createAsyncRequest(URI uri, HttpMethod httpMethod) throws IOException {
AsyncClientHttpRequest request = requestFactory.createAsyncRequest(uri, httpMethod);
if (shouldBuffer(uri, httpMethod)) {
return new BufferingAsyncClientHttpRequestWrapper(request);
}
else {
return request;
}
}
protected boolean shouldBuffer(URI uri, HttpMethod httpMethod) {
return true;
}
}
BufferingAsyncClientHttpRequestWrapper.java
public class BufferingAsyncClientHttpRequestWrapper extends AbstractBufferingAsyncClientHttpRequest {
private final AsyncClientHttpRequest request;
public BufferingAsyncClientHttpRequestWrapper(AsyncClientHttpRequest asyncClientHttpRequest){
this.request=asyncClientHttpRequest;
}
@Override
public HttpMethod getMethod() {
return this.request.getMethod();
}
@Override
public URI getURI() {
return this.request.getURI();
}
@Override
protected ListenableFuture<ClientHttpResponse> executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException {
this.request.getHeaders().putAll(headers);
if(bufferedOutput.length>0){
StreamUtils.copy(bufferedOutput,this.request.getBody());
}
ListenableFuture<ClientHttpResponse> futureResponse = this.request.executeAsync();
ListenableFutureAdapter<ClientHttpResponse,ClientHttpResponse> bufferedResponse =
new ListenableFutureAdapter<ClientHttpResponse, ClientHttpResponse>(futureResponse) {
@Override
protected ClientHttpResponse adapt(ClientHttpResponse adapteeResult) throws ExecutionException {
return new BufferingClientHttpResponseWrapper(adapteeResult);
}
};
return bufferedResponse;
}
}
关于spring - 如何将 BufferingClientHttpResponseWrapper 与 HttpComponentsAsyncClientHttpRequestFactory 结合使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42309192/