启用Apache HttpClient的日志记录

2025/04/12

1. 概述

在本教程中,我们将展示如何Apache HttpClient中启用日志记录功能。此外,我们还将解释该库内部是如何实现日志记录的。之后,我们将展示如何启用不同级别的日志记录。

2. 日志记录实现

HttpClient库提供了高效、最新、功能丰富的HTTP协议客户端站点实现。

事实上,作为一个库,HttpClient并不强制要求日志记录实现。出于这个目的,4.5版本使用Commons Logging提供日志记录功能。同样,最新版本5.1使用了SLF4J提供的日志记录门面;这两个版本都使用层次结构模式来将记录器与其配置进行匹配。

因此,可以为单个类或与相同功能相关的所有类设置记录器。

3. 日志类型

我们来看看库定义的日志级别。我们可以区分3种类型的日志:

  • 上下文日志:记录有关HttpClient所有内部操作的信息。它还包含线路日志和头日志。
  • 线路日志记录:仅记录传输到服务器和从服务器传输的数据
  • 标头日志记录:仅记录HTTP标头

在4.5版本中对应的包是org.apache.http.impl.client和org.apache.http.wire、org.apache.http.headers

因此,在5.1版本中,有org.apache.hc.client5.http、org.apache.hc.client5.http.wire和org.apache.hc.client5.http.headers包。

4. Log4j配置

让我们看看如何在两个版本中启用日志功能,我们的目标是在两个版本中实现相同的灵活性;在4.1版本中,我们将日志重定向到SLF4j,这样,就可以使用不同的日志框架了

4.1 版本4.5配置

让我们添加httpclient依赖:

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.5.8</version>
    <exclusions>
        <exclusion>
            <artifactId>commons-logging</artifactId>
            <groupId>commons-logging</groupId>
        </exclusion>
    </exclusions>
</dependency>

我们将使用jcl-over-slf4j将日志重定向到SLF4J,因此我们排除了commons-logging。接下来,让我们在JCL和SLF4J之间的桥接中添加一个依赖:

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>jcl-over-slf4j</artifactId>
    <version>1.7.32</version>
</dependency>

因为SLF4J只是一个门面,所以我们需要一个绑定。在我们的示例中,我们将使用logback

<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.6</version>
</dependency>

现在让我们创建ApacheHttpClientUnitTest类:

public class ApacheHttpClientUnitTest {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    public static final String DUMMY_URL = "https://postman-echo.com/get";

    @Test
    public void whenUseApacheHttpClient_thenCorrect() throws IOException {
        HttpGet request = new HttpGet(DUMMY_URL);

        try (CloseableHttpClient client = HttpClients.createDefault();
             CloseableHttpResponse response = client.execute(request)) {
            HttpEntity entity = response.getEntity();
            logger.debug("Response -> {}",  EntityUtils.toString(entity));
        }
    }
}

测试获取虚拟网页并将内容打印到日志中。

现在让我们用logback.xml文件定义一个记录器配置:

<configuration debug="false">
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%date [%level] %logger - %msg %n</pattern>
        </encoder>
    </appender>

    <logger name="cn.tuyucheng.taketoday.httpclient.readresponsebodystring" level="debug"/>
    <logger name="org.apache.http" level="debug"/>

    <root level="WARN">
        <appender-ref ref="stdout"/>
    </root>
</configuration>

运行我们的测试后,可以在控制台中找到所有HttpClient的日志:

...
2021-06-19 22:24:45,378 [DEBUG] org.apache.http.impl.execchain.MainClientExec - Executing request GET /get HTTP/1.1 
2021-06-19 22:24:45,378 [DEBUG] org.apache.http.impl.execchain.MainClientExec - Target auth state: UNCHALLENGED 
2021-06-19 22:24:45,379 [DEBUG] org.apache.http.impl.execchain.MainClientExec - Proxy auth state: UNCHALLENGED 
2021-06-19 22:24:45,382 [DEBUG] org.apache.http.headers - http-outgoing-0 >> GET /get HTTP/1.1 
...

4.2 版本5.1配置

现在我们来看看更高版本,它包含重新设计的日志记录,因此,它使用SLF4J而不是Commons Logging。因此,记录器门面的绑定是唯一的附加依赖,因此,我们将像第一个示例中一样使用logback-classic。

让我们添加httpclient5依赖:

<dependency>
    <groupId>org.apache.httpcomponents.client5</groupId>
    <artifactId>httpclient5</artifactId>
    <version>5.1</version>
</dependency>

让我们添加一个与前面的例子类似的测试:

public class ApacheHttpClient5UnitTest {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    public static final String DUMMY_URL = "https://postman-echo.com/get";

    @Test
    public void whenUseApacheHttpClient_thenCorrect() throws IOException, ParseException {
        HttpGet request = new HttpGet(DUMMY_URL);

        try (CloseableHttpClient client = HttpClients.createDefault();
             CloseableHttpResponse response = client.execute(request)) {
            HttpEntity entity = response.getEntity();
            logger.debug("Response -> {}", EntityUtils.toString(entity));
        }
    }
}

接下来,我们需要在logback.xml文件中添加一个记录器:

<configuration debug="false">
...
    <logger name="org.apache.hc.client5.http" level="debug"/>
...
</configuration>

我们来运行测试类ApacheHttpClient5UnitTest并检查输出,它与旧版本类似:

...
2021-06-19 22:27:16,944 [DEBUG] org.apache.hc.client5.http.impl.classic.InternalHttpClient - ep-0000000000 endpoint connected 
2021-06-19 22:27:16,944 [DEBUG] org.apache.hc.client5.http.impl.classic.MainClientExec - ex-0000000001 executing GET /get HTTP/1.1 
2021-06-19 22:27:16,944 [DEBUG] org.apache.hc.client5.http.impl.classic.InternalHttpClient - ep-0000000000 start execution ex-0000000001 
2021-06-19 22:27:16,944 [DEBUG] org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager - ep-0000000000 executing exchange ex-0000000001 over http-outgoing-0 
2021-06-19 22:27:16,960 [DEBUG] org.apache.hc.client5.http.headers - http-outgoing-0 >> GET /get HTTP/1.1 
...

5. 总结

首先,我们解释了该库是如何实现日志记录的,其次,我们配置了两个版本的日志记录,并执行了一些简单的测试用例来展示输出。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章