You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Apache HttpClient 4异步客户端中于请求发起前设置Bearer Token

Apache HttpClient 4 实现请求实际执行前设置Bearer Token

问题背景

使用Apache HttpClient 4异步客户端时,通过HttpRequestInterceptor设置Bearer Token,发现拦截器在提交请求阶段就全部触发,而非实际发送请求时。大量请求场景下,提前生成的Token可能在请求实际发送时过期。期望实现类似HttpClient 5的拦截器行为:在请求实际执行前触发Token设置逻辑。

测试代码如下:

public class Test {
    public static void main(final String[] args) {
        try (CloseableHttpAsyncClient httpclient = HttpAsyncClients.custom().setMaxConnTotal(2)
                .addInterceptorFirst(new Interceptor()).build()) {
            httpclient.start();
            final CountDownLatch latchComplete = new CountDownLatch(10);
            for (int i = 0; i < 10; i++) {
                httpclient.execute(new HttpGet("https://www.google.com"), new CallBack(latchComplete));
            }
            latchComplete.await();
        } catch (final IOException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    static class CallBack implements FutureCallback<HttpResponse> {
        CountDownLatch latchComplete;

        CallBack(final CountDownLatch pCountDownLatch) {
            this.latchComplete = pCountDownLatch;
        }

        @Override
        public void completed(final HttpResponse pHttpResponse) {
            this.latchComplete.countDown();
            System.out.println("completed");
        }

        @Override
        public void failed(final Exception pE) {
            this.latchComplete.countDown();
            System.out.println("failed");
        }

        @Override
        public void cancelled() {
            this.latchComplete.countDown();
            System.out.println("cancelled");
        }
    }

    static class Interceptor implements HttpRequestInterceptor {
        @Override
        public void process(final HttpRequest pHttpRequest, final HttpContext pHttpContext)
                throws HttpException, IOException {
            System.out.println("Interceptor");
        }
    }
}

预期输出(拦截器与请求完成交替触发):

Interceptor
Interceptor
completed
completed
Interceptor
completed
Interceptor
completed
Interceptor
completed
Interceptor
completed
Interceptor
completed
Interceptor
completed
Interceptor
completed
Interceptor
completed

实际输出(所有拦截器先触发,再批量完成请求):

Interceptor
Interceptor
Interceptor
Interceptor
Interceptor
Interceptor
Interceptor
Interceptor
Interceptor
Interceptor
completed
completed
completed
completed
completed
completed
completed
completed
completed
completed

解决方案

HttpClient 4异步客户端的HttpRequestInterceptor确实会在请求提交时立即执行,而非实际发送阶段。要实现请求实际执行前设置Token,可通过**自定义HttpAsyncRequestProducer**来延迟请求的构建逻辑,具体步骤如下:

1. 自定义请求生成器

实现HttpAsyncRequestProducer接口,在generateRequest方法中添加Token设置逻辑。该方法会在请求实际准备发送(连接可用时)被调用,保证Token是最新的:

static class TokenAddingRequestProducer implements HttpAsyncRequestProducer {
    private final HttpGet originalRequest;

    public TokenAddingRequestProducer(HttpGet originalRequest) {
        this.originalRequest = originalRequest;
    }

    @Override
    public HttpContext createContext() {
        return new BasicHttpContext();
    }

    @Override
    public HttpRequest generateRequest() throws IOException, HttpException {
        // 实际发送请求前获取最新Token并设置
        String latestToken = getLatestBearerToken();
        originalRequest.setHeader("Authorization", "Bearer " + latestToken);
        System.out.println("Interceptor (实际发送前设置Token)");
        return originalRequest;
    }

    @Override
    public void requestCompleted(HttpContext context) {}

    @Override
    public void failed(Exception ex) {}

    @Override
    public void produceContent(ContentEncoder encoder, IOControl ioControl) throws IOException {}

    @Override
    public void resetRequest() throws IOException {}

    @Override
    public void close() throws IOException {}

    // 模拟获取最新Token的逻辑,替换为实际业务实现
    private String getLatestBearerToken() {
        return "fresh-token-" + System.currentTimeMillis();
    }
}

2. 修改请求提交逻辑

将原有的HttpGet请求替换为自定义的TokenAddingRequestProducer:

// 替换原execute调用
httpclient.execute(new TokenAddingRequestProducer(new HttpGet("https://www.google.com")), new CallBack(latchComplete));

效果说明

修改后,generateRequest方法会在请求实际发送前触发,拦截器/Token设置逻辑与请求完成操作交替执行,输出符合预期,有效避免Token提前生成导致的过期问题。

内容的提问来源于stack exchange,提问作者Suzuki Yuu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 18:23:19