Spring RestTemplate - 如何启用请求/响应的完整调试/日志记录?

新手上路,请多包涵

我使用 Spring RestTemplate 已经有一段时间了,当我尝试调试它的请求和响应时,我总是碰壁。我基本上希望看到与打开“详细”选项使用 curl 时看到的相同的东西。例如 :

 curl -v http://twitter.com/statuses/public_timeline.rss

将显示发送的数据和接收的数据(包括标头、cookie 等)。

我检查了一些相关的帖子,例如: 如何在 Spring RestTemplate 中记录响应? 但我还没有设法解决这个问题。

一种方法是实际更改 RestTemplate 源代码并在那里添加一些额外的日志记录语句,但我会发现这种方法确实是最后的手段。应该有一些方法可以告诉 Spring Web Client/RestTemplate 以更友好的方式记录所有内容。

我的目标是能够使用以下代码做到这一点:

 restTemplate.put("http://someurl", objectToPut, urlPathValues);

然后在日志文件或控制台中获得相同类型的调试信息(就像我使用 curl 获得的那样)。我相信这对于使用 Spring RestTemplate 并遇到问题的任何人都非常有用。使用 curl 来调试您的 RestTemplate 问题只是不起作用(在某些情况下)。

原文由 Paul Sabou 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.5k
2 个回答

我终于找到了一种以正确方式做到这一点的方法。大多数解决方案来自 How do I configure Spring and SLF4J so I can get logging?

似乎有两件事需要做:

  1. 在 log4j.properties 中添加以下行: log4j.logger.httpclient.wire=DEBUG
  2. 确保 spring 不会忽略您的日志记录配置

第二个问题主要发生在使用 slf4j 的 spring 环境中(就像我的情况一样)。因此,当使用 slf4j 时,请确保发生以下两件事:

  1. 您的类路径中没有 commons-logging 库:这可以通过在您的 pom 中添加排除描述符来完成:
            <exclusions><exclusion>
               <groupId>commons-logging</groupId>
               <artifactId>commons-logging</artifactId>
           </exclusion>
       </exclusions>

  1. log4j.properties 文件存储在 spring 可以找到/看到它的类路径中的某个位置。如果您对此有疑问,最后的解决方案是将 log4j.properties 文件放在默认包中(这不是一个好习惯,但只是为了让事情按您的预期工作)

原文由 Paul Sabou 发布,翻译遵循 CC BY-SA 3.0 许可协议

只是为了通过完整实施 ClientHttpRequestInterceptor 来完成示例以跟踪请求和响应:

 import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;

public class LoggingRequestInterceptor implements ClientHttpRequestInterceptor {

    final static Logger log = LoggerFactory.getLogger(LoggingRequestInterceptor.class);

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        traceRequest(request, body);
        ClientHttpResponse response = execution.execute(request, body);
        traceResponse(response);
        return response;
    }

    private void traceRequest(HttpRequest request, byte[] body) throws IOException {
        log.info("===========================request begin================================================");
        log.debug("URI         : {}", request.getURI());
        log.debug("Method      : {}", request.getMethod());
        log.debug("Headers     : {}", request.getHeaders() );
        log.debug("Request body: {}", new String(body, "UTF-8"));
        log.info("==========================request end================================================");
    }

    private void traceResponse(ClientHttpResponse response) throws IOException {
        StringBuilder inputStringBuilder = new StringBuilder();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(response.getBody(), "UTF-8"));
        String line = bufferedReader.readLine();
        while (line != null) {
            inputStringBuilder.append(line);
            inputStringBuilder.append('\n');
            line = bufferedReader.readLine();
        }
        log.info("============================response begin==========================================");
        log.debug("Status code  : {}", response.getStatusCode());
        log.debug("Status text  : {}", response.getStatusText());
        log.debug("Headers      : {}", response.getHeaders());
        log.debug("Response body: {}", inputStringBuilder.toString());
        log.info("=======================response end=================================================");
    }

}

然后实例化 RestTemplate 使用 BufferingClientHttpRequestFactoryLoggingRequestInterceptor

 RestTemplate restTemplate = new RestTemplate(new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory()));
List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
interceptors.add(new LoggingRequestInterceptor());
restTemplate.setInterceptors(interceptors);

BufferingClientHttpRequestFactory 是必需的,因为我们想在拦截器和初始调用代码中都使用响应主体。默认实现只允许读取响应主体一次。

原文由 sofiene zaghdoudi 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题