【问题标题】:How to update the settings of an HttpClient in httpclient 4.3+?如何在 httpclient 4.3+ 中更新 HttpClient 的设置?
【发布时间】:2014-12-19 10:44:10
【问题描述】:

在 httpclient 4.3 中,如果您遵守所有弃用条款,则必须使用 HttpClientBuilder(文档 here)构建和配置您的 HttpClient。方法很明确,看起来很容易使用,HttpClient's interface 很清楚。但也许有点太多了。

在我自己的情况下,我必须继承 Spring 的 HttpComponentsHttpInvokerRequestExecutor(文档 here)。结果,我可以轻松获得HttpClient,但我对这个对象的了解只是它实现了接口。

由于客户端已经构建,而我对它的实现一无所知,我无法访问诸如AbstractHttpClientsetHttpRequestRetryHandleraddRequestInterceptor 之类的方法(虽然是的,我知道,它们已被弃用)。

那么,更新这个HttpClient 设置的最干净的方法是什么(重试处理程序和请求拦截器是我目前最关心的)?我应该...

  • ...野蛮地将我的客户投给AbstractHttpClient,希望我能一直收到这个实现?
  • ... 在我的 HttpInvokerRequestExecutor 的构造函数中创建一个新的HttpClient,并得到类似下面复制的示例?我可能会补充一点,Spring 的构造函数(至少在 3.2.4 中)也使用了 httpclient 4.3 中不推荐使用的方法。使用此策略是否会遗漏任何副作用?
  • ...做一些我还没有提议的事情?

自定义构造函数示例:

public CustomHttpInvokerRequestExecutor() {
    super(); // will create an HttpClient
    // Now overwrite the client the super constructor created
    setHttpClient(HttpClientBuilder.custom(). ... .build());
}

【问题讨论】:

    标签: java spring httpclient apache-httpclient-4.x


    【解决方案1】:

    做一些我还没有提议的事情?

    我的建议是重新考虑整个方法。不应该在运行时删除/添加协议拦截器,而是应该使用HttpContext 实例来更新请求执行上下文并将配置传递给协议拦截器

    http://hc.apache.org/httpcomponents-core-4.4.x/tutorial/html/fundamentals.html#d5e306 http://hc.apache.org/httpcomponents-client-4.3.x/tutorial/html/fundamentals.html#d5e223

    CloseableHttpClient client = HttpClientBuilder.create()
            .addInterceptorFirst(new HttpRequestInterceptor() {
                @Override
                public void process(
                        final HttpRequest request,
                        final HttpContext context) throws HttpException, IOException {
                    boolean b = (Boolean) context.getAttribute("my-config");
                    if (b) {
                        // do something useful
                    }
    
                }
            })
            .build();
    HttpClientContext context = HttpClientContext.create();
    context.setAttribute("my-config", Boolean.TRUE);
    CloseableHttpResponse response1 = client.execute(new HttpGet("/"), context);
    response1.close();
    context.setAttribute("my-config", Boolean.FALSE);
    CloseableHttpResponse response2 = client.execute(new HttpGet("/"), context);
    response2.close();
    

    【讨论】:

    • 我自己没有想到拦截器。这实际上是从 httpclient3 到 httpclient4 的迁移,在某些情况下,我需要抢占式身份验证。我发现很多例子都使用了拦截器(an example)。此外,由于我重写了另一个类,我只能访问传递给我的超级方法的参数,这些参数不包括上下文。我尝试在对象中找到它,但没有成功。请参阅 HttpComponentsHttpInvokerRequestExecutor 的文档。
    • 您实际上并不需要拦截器来强制 HttpClient 抢先进行身份验证。见hc.apache.org/httpcomponents-client-4.3.x/httpclient/examples/…
    • 是的,但这里的拦截器似乎是我获得访问 HttpContext 以及因此访问我的 CredentialProvider 的最佳方式。还是我错过了什么?另外,您关注的是拦截器部分,尽管这只是问题的一个方面。真正的问题是:如何配置我的 RequestExecutor 的客户端?一旦我知道如何做到这一点,我愿意尽可能多地听取您在配置时应该做什么的建议,但我认为我们应该先做第一件事。
    • 推荐的 HttpClient 配置方法将一个 HttpClient 实例连接在一起,该实例是不可变的,可以由多个线程同时共享和使用,然后使用 HttpContext 实例来自定义单个请求执行。永远不需要在运行时删除拦截器或处理程序。您是否决定采用推荐的方法完全取决于您。
    • 不幸的是,与 HttpComponentsClientHttpRequestFactory 不同,HttpComponentsHttpInvokerRequestExecutor 不提供为请求执行设置自定义上下文的方法。您很可能必须继承执行器并覆盖其#executeHttpPost 方法或向 Spring 开发人员提出增强请求。他们目前正在完善其基于 HC 的组件的 API,因此他们很可能会接受这样的请求。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-10
    相关资源
    最近更新 更多