1. 概述

AsyncHttpClient (AHC) 是一个基于 Netty 构建的库,旨在简化异步执行 HTTP 请求和处理响应的过程。

本文将介绍如何配置和使用 AHC 的 HTTP 客户端,以及如何执行请求并处理响应。

2. 环境配置

最新版本可在 Maven 仓库 获取。注意:务必使用 org.asynchttpclient 分组的依赖,而非 com.ning 分组的旧版本:

<dependency>
    <groupId>org.asynchttpclient</groupId>
    <artifactId>async-http-client</artifactId>
    <version>2.2.0</version>
</dependency>

3. HTTP 客户端配置

最简单的客户端获取方式是通过 Dsl 类的静态方法:

AsyncHttpClient client = Dsl.asyncHttpClient();

若需自定义配置(如超时、代理、证书等),可使用 DefaultAsyncHttpClientConfig.Builder

DefaultAsyncHttpClientConfig.Builder clientBuilder = Dsl.config()
  .setConnectTimeout(500)
  .setProxyServer(new ProxyServer(...));
AsyncHttpClient client = Dsl.asyncHttpClient(clientBuilder);

⚠️ 关键点

  • 客户端实例应在整个应用中复用,避免为每个请求创建新实例(内部会创建线程池和连接池,重复创建会导致性能问题)
  • 使用完毕后必须调用 close() 方法,防止内存泄漏或资源挂起

4. 创建 HTTP 请求

AHC 支持两种请求创建方式:

  • 绑定请求 (Bound Request)
  • 非绑定请求 (Unbound Request)

两者性能无本质差异,仅是 API 设计不同。绑定请求与创建它的客户端强关联,默认继承客户端配置(如 disableUrlEncoding 标志),而非绑定请求需显式配置。

✅ 通过 VM 参数动态修改配置示例:

java -jar -Dorg.asynchttpclient.disableUrlEncodingForBoundRequests=true

4.1. 绑定请求

使用 AsyncHttpClient 类的 prepare* 方法创建,例如 GET 请求:

BoundRequestBuilder getRequest = client.prepareGet("http://www.baeldung.com");

4.2. 非绑定请求

通过 RequestBuilderDsl 工具类创建:

// 方式一:RequestBuilder
Request getRequest = new RequestBuilder(HttpConstants.Methods.GET)
  .setUrl("http://www.baeldung.com")
  .build();

// 方式二:Dsl 工具类
Request getRequest = Dsl.get("http://www.baeldung.com").build();

5. 执行 HTTP 请求

AHC 支持同步和异步两种执行模式:

  • 绑定请求:使用 BoundRequestBuilder.execute()
  • 非绑定请求:使用 AsyncHttpClient.executeRequest()

5.1. 同步执行

通过阻塞 Future 对象模拟同步调用(仅建议调试时使用):

// 绑定请求
Future<Response> responseFuture = boundGetRequest.execute();
Response response = responseFuture.get();

// 非绑定请求
Future<Response> responseFuture = client.executeRequest(unboundRequest);
Response response = responseFuture.get();

生产环境慎用:同步调用会阻塞线程,降低吞吐量。

5.2. 异步执行

AHC 提供三种异步监听器:

  1. AsyncHandler(细粒度控制)
  2. AsyncCompletionHandler(简化版)
  3. ListenableFuture(回调式)

5.2.1. AsyncHandler 监听器

可拦截 HTTP 请求各阶段事件(状态/头部/响应体):

request.execute(new AsyncHandler<Object>() {
    @Override
    public State onStatusReceived(HttpResponseStatus status) {
        // 处理状态码
        return State.CONTINUE; // 继续
    }

    @Override
    public State onHeadersReceived(HttpHeaders headers) {
        // 处理响应头
        return State.CONTINUE;
    }

    @Override
    public State onBodyPartReceived(HttpResponseBodyPart bodyPart) {
        // 处理响应体分块
        return State.CONTINUE;
    }

    @Override
    public void onThrowable(Throwable t) {
        // 异常处理
    }

    @Override
    public Object onCompleted() {
        // 请求完成
        return null;
    }
});

⚠️ 注意

  • 返回 State.ABORT 可提前终止请求处理
  • 非线程安全,禁止在并发请求中复用

5.2.2. AsyncCompletionHandler 监听器

继承 AsyncHandler 并简化完成逻辑(其他方法默认返回 State.CONTINUE):

request.execute(new AsyncCompletionHandler<Object>() {
    @Override
    public Object onCompleted(Response response) {
        // 直接处理完整响应
        return response;
    }
});

5.2.3. ListenableFuture 监听器

支持添加回调监听器,并可指定线程池执行:

ListenableFuture<Response> listenableFuture = client.executeRequest(unboundRequest);
listenableFuture.addListener(() -> {
    Response response = listenableFuture.get();
    LOG.debug("状态码: " + response.getStatusCode());
}, Executors.newCachedThreadPool());

额外能力:可将 ListenableFuture 转换为 CompletableFuture

7. 总结

AHC 是功能强大的 HTTP 客户端库,核心优势包括:

  • 简单灵活的客户端配置
  • 同步/异步请求双模式支持
  • 丰富的异步监听器机制

完整示例代码见 GitHub 仓库


原始标题:Asynchronous HTTP with async-http-client in Java