代码之家  ›  专栏  ›  技术社区  ›  Abhijit Sarkar

如何使用java.net.http.HttpClient记录请求/响应?

  •  6
  • Abhijit Sarkar  · 技术社区  · 7 年前

    这个 HttpClient 在Java9中实验性地引入,现在在Java11中是稳定的,但毫不奇怪,几乎没有项目实际使用它。文件几乎不存在。

    在进行HTTP调用时,最常见的问题之一是记录请求/响应。您将如何使用 HttpClient 当然,没有在每次通话中手动记录?有没有像所有其他HTTP客户机那样提供的拦截器机制?

    2 回复  |  直到 7 年前
        1
  •  11
  •   Karol Dowbecki    7 年前

    如果我们看看 jdk.internal.net.http.common.DebugLogger System.Logger ,然后将使用 System.LoggerFinder 选择记录器框架。JUL是默认选择。记录器名称为:

    • jdk.internal.httpclient.debug
    • jdk.internal.httpclient.hpack.debug

    可以通过将它们设置为系统属性来启用它们。例如,与 -Djdk.internal.httpclient.debug=true 将产生:

    DEBUG: [main] [147ms] HttpClientImpl(1) proxySelector is sun.net.spi.DefaultProxySelector@6dde5c8c (user-supplied=false)
    DEBUG: [main] [183ms] HttpClientImpl(1) ClientImpl (async) send https://http2.github.io/ GET
    DEBUG: [main] [189ms] Exchange establishing exchange for https://http2.github.io/ GET,
         proxy=null
    DEBUG: [main] [227ms] PlainHttpConnection(?) Initial receive buffer size is: 43690
    DEBUG: [main] [237ms] PlainHttpConnection(SocketTube(1)) registering connect event
    DEBUG: [HttpClient-1-SelectorManager] [239ms] SelectorAttachment Registering jdk.internal.net.http.PlainHttpConnection$ConnectEvent@354bf356 for 8 (true)
    ...
    
        2
  •  19
  •   Nathan    5 年前

    您可以通过指定 -Djdk.httpclient.HttpClient.log=requests 在Java命令行上。

    http://hg.openjdk.java.net/jdk/jdk/file/tip/test/jdk/java/net/httpclient/offline/

    根据您希望实现的目标,您也可以使用“DelegatingHttpClient”来拦截和记录请求和响应。

    除了JavaAPI文档之外,还有一些高级文档 http://openjdk.java.net/groups/net/httpclient/index.html

    补充说明:

    jdk.httpclient.HttpClient.log

    -Djdk.httpclient.HttpClient.log=
           errors,requests,headers,
           frames[:control:data:window:all],content,ssl,trace,channel,all
    
        3
  •  4
  •   Maxime Carbonneau-Leclerc    7 年前

    在我们这边,我们没有找到 -Djdk.internal.httpclient.debug send 但是 sendAsync 方法:

    public class HttpClientLoggingDecorator extends HttpClient {
    
      private static final Logger logger = Logger.getLogger(HttpClientLoggingDecorator.class.getName());
    
      private final HttpClient client;
    
      ...
    
      @Override
      public <T> HttpResponse<T> send(HttpRequest req, HttpResponse.BodyHandler<T> responseBodyHandler)
        throws IOException,
          InterruptedException
      {
        subscribeLoggerToRequest(req);
    
        HttpResponse<T> response = client.send(req, responseBodyHandler);
    
        logResponse(response);
        return response;
      }
    
      private void subscribeLoggerToRequest(HttpRequest req) {
        // define a consumer for how you want to log
        // Consumer<String> bodyConsumer = ...;
        if (req.bodyPublisher().isPresent()) {
          req.bodyPublisher()
                  .ifPresent(bodyPublisher -> bodyPublisher.subscribe(new HttpBodySubscriber(bodyConsumer)));
        } else {
          bodyConsumer.accept(NO_REQUEST_BODY);
        }
      }
    
      private <T> void logResponse(HttpResponse<T> response) {
        // String responseLog = ...;
        logger.info(responseLog);
      }
    
    }
    

    这里是 HttpBodySubscriber

    public class HttpBodySubscriber implements Flow.Subscriber<ByteBuffer> {
    
      private static final long UNBOUNDED = Long.MAX_VALUE;
    
      private final Consumer<String> logger;
    
      public HttpBodySubscriber(Consumer<String> logger) {
        this.logger = logger;
      }
    
      @Override
      public void onSubscribe(Flow.Subscription subscription) {
        subscription.request(UNBOUNDED);
      }
    
      @Override
      public void onNext(ByteBuffer item) {
        logger.accept(new String(item.array(), StandardCharsets.UTF_8));
      }
    
      @Override
      public void onError(Throwable throwable) {
      }
    
      @Override
      public void onComplete() {
      }
    
    }
    
    推荐文章