1. 概述

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

2. 日志记录实现

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

事实上,作为一个库,HttpClient 并不强制实现日志记录 。出于这个目的,4.5 版本提供了Commons Logging日志。同样,最新版本 5.1 使用SLF4J提供的日志外观。两个版本都使用层次结构来将记录器与其配置相匹配。

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

3. 日志类型

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

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

在版本 4.5 中,相应的包 org.apache.http.impl.clientorg.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="com.baeldung.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. 结论

关于如何为 Apache 的 HttpClient 配置日志记录的简短教程到此结束。首先,我们解释了如何在库中实现日志记录。其次,我们在两个版本中配置日志记录并执行简单的测试用例来显示输出。

与往常一样,该示例的源代码可以在 GitHub 上获取。