为什么我的自定义 ClientHttpRequestInterceptor 响应为空
Why my custom ClientHttpRequestInterceptor with empty response
我已经为我的自定义日志记录拦截器完成了以下操作
public class HttpLoggingInterceptor implements ClientHttpRequestInterceptor {
private final static Logger log = LoggerFactory.getLogger(HttpLoggingInterceptor.class);
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
logRequest(request, body);
ClientHttpResponse response = execution.execute(request, body);
logResponse(response);
return response;
}
private void logRequest(HttpRequest request, byte[] body) throws IOException {
log.info("Request URI : {}, Method : {}, Headers : {}, Request body : {}", request.getURI(), request.getMethod(), request.getHeaders(), new String(body, "UTF-8"));
}
private void logResponse(ClientHttpResponse response) throws IOException {
log.info("Response Status code : {}, Status text : {}, Headers : {}, Response body: {}", response.getStatusCode(), response.getStatusText(), response.getHeaders(), StreamUtils.copyToString(response.getBody(), Charset.defaultCharset()));
}
}
我正在将拦截器设置为 restTemplate
@Autowired
public RestTemplate restTemplate;
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
List<ClientHttpRequestInterceptor> clientHttpRequestInterceptors = new ArrayList<>();
clientHttpRequestInterceptors.add(new HttpLoggingInterceptor());
// clientHttpRequestInterceptors.addAll(restTemplate.getInterceptors());
restTemplate.setInterceptors(clientHttpRequestInterceptors);
// restTemplate.setInterceptors(Collections.singletonList(new HttpLoggingInterceptor()));
}
记录器正确地将响应打印到控制台,但最后响应返回给调用者为空。我无法调试和弄明白。
我发现 StreamUtils.copyToString(response.getBody(), Charset.defaultCharset())
正在读取输入流一次,它不再包含响应主体(现在是空的)
还有其他人也面临同样的问题并且想复制 InputStream 而不从原始 InputStream 读取它吗?
由于输入流只能被消耗一次,并且没有 reset()
或 mark(***)
函数可用于 sun.net.www.protocol.http.HttpURLConnection$HttpInputStream
。
只有一种方法可以通过以下方式创建 restTemplate 来多次读取响应。
@Bean
public RestTemplate getfxoWsClientRestTemplate(){
RestTemplate restTemplate = new RestTemplate(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));
restTemplate.setInterceptors(Collections.singletonList(new HttpLoggingInterceptor()));
return restTemplate;
}
而LoggingIntercepter
可以这样写
public class HttpLoggingInterceptor implements ClientHttpRequestInterceptor {
private final static Logger logger = LoggerFactory.getLogger(HttpLoggingInterceptor.class);
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
logger.info("request method: {}, request URI: {}, request headers: {}, request body: {}",
request.getMethod(), request.getURI(), request.getHeaders(), new String(body, Charset.forName("UTF-8")));
ClientHttpResponse response = execution.execute(request, body);
logger.info("response status code: {}, response headers: {}, response body: {}",
response.getStatusCode(), response.getHeaders(), new String(ByteStreams.toByteArray(response.getBody()), Charset.forName("UTF-8")));
return response;
}
}
我已经为我的自定义日志记录拦截器完成了以下操作
public class HttpLoggingInterceptor implements ClientHttpRequestInterceptor {
private final static Logger log = LoggerFactory.getLogger(HttpLoggingInterceptor.class);
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
logRequest(request, body);
ClientHttpResponse response = execution.execute(request, body);
logResponse(response);
return response;
}
private void logRequest(HttpRequest request, byte[] body) throws IOException {
log.info("Request URI : {}, Method : {}, Headers : {}, Request body : {}", request.getURI(), request.getMethod(), request.getHeaders(), new String(body, "UTF-8"));
}
private void logResponse(ClientHttpResponse response) throws IOException {
log.info("Response Status code : {}, Status text : {}, Headers : {}, Response body: {}", response.getStatusCode(), response.getStatusText(), response.getHeaders(), StreamUtils.copyToString(response.getBody(), Charset.defaultCharset()));
}
}
我正在将拦截器设置为 restTemplate
@Autowired
public RestTemplate restTemplate;
@Override
public void onApplicationEvent(ApplicationReadyEvent event) {
List<ClientHttpRequestInterceptor> clientHttpRequestInterceptors = new ArrayList<>();
clientHttpRequestInterceptors.add(new HttpLoggingInterceptor());
// clientHttpRequestInterceptors.addAll(restTemplate.getInterceptors());
restTemplate.setInterceptors(clientHttpRequestInterceptors);
// restTemplate.setInterceptors(Collections.singletonList(new HttpLoggingInterceptor()));
}
记录器正确地将响应打印到控制台,但最后响应返回给调用者为空。我无法调试和弄明白。
我发现 StreamUtils.copyToString(response.getBody(), Charset.defaultCharset())
正在读取输入流一次,它不再包含响应主体(现在是空的)
还有其他人也面临同样的问题并且想复制 InputStream 而不从原始 InputStream 读取它吗?
由于输入流只能被消耗一次,并且没有 reset()
或 mark(***)
函数可用于 sun.net.www.protocol.http.HttpURLConnection$HttpInputStream
。
只有一种方法可以通过以下方式创建 restTemplate 来多次读取响应。
@Bean
public RestTemplate getfxoWsClientRestTemplate(){
RestTemplate restTemplate = new RestTemplate(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));
restTemplate.setInterceptors(Collections.singletonList(new HttpLoggingInterceptor()));
return restTemplate;
}
而LoggingIntercepter
可以这样写
public class HttpLoggingInterceptor implements ClientHttpRequestInterceptor {
private final static Logger logger = LoggerFactory.getLogger(HttpLoggingInterceptor.class);
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
logger.info("request method: {}, request URI: {}, request headers: {}, request body: {}",
request.getMethod(), request.getURI(), request.getHeaders(), new String(body, Charset.forName("UTF-8")));
ClientHttpResponse response = execution.execute(request, body);
logger.info("response status code: {}, response headers: {}, response body: {}",
response.getStatusCode(), response.getHeaders(), new String(ByteStreams.toByteArray(response.getBody()), Charset.forName("UTF-8")));
return response;
}
}