【问题标题】:Single HttpClientContext for multiple threads多个线程的单个 HttpClientContext
【发布时间】:2018-01-30 20:15:17
【问题描述】:

我正在使用 apache HttpClient 4.5 在 java 中处理 http 请求。

根据文档 HttpClient 是线程安全的,因此我们可以为所有线程使用相同的 HttpClient 实例,但 HttpContext 应由每个执行线程维护。

对于身份验证(NTLM 身份验证),我们需要将 CredentialsProvider 设置为上下文,这将在服务器上进行身份验证。

要求

所有请求都将访问具有相同身份验证详细信息的同一台服务器。我只想在应用程序初始化或首次向服务器发出请求时进行一次身份验证,所有其他请求都应在同一个会话中服务,但可以来自不同的线程。

我可以使用相同的上下文,因为使用相同的身份验证详细信息访问同一台服务器,还是有其他方法可以实现?

【问题讨论】:

    标签: apache-httpclient-4.x


    【解决方案1】:

    尽管HttpContext 实例不应该在线程之间共享,但在多个上下文之间共享线程安全对象并没有错。例如,可以轻松地将相同的 CredentialsProviderAuthCache 实例与多个并发上下文一起使用。

    // External dependencies
    CloseableHttpClient client;
    CredentialsProvider credentialsProvider;
    AuthCache authCache;
    CookieStore cookieStore;
    Principal userPrincipal;
    
    // request execution
    HttpClientContext context = HttpClientContext.create();
    context.setCredentialsProvider(credentialsProvider);
    context.setAuthCache(authCache);
    context.setCookieStore(cookieStore);
    context.setUserToken(userPrincipal);
    HttpGet httpGet = new HttpGet("http://targethost/");
    try (CloseableHttpResponse response1 = client.execute(httpGet, context)) {
        System.out.println(response1.getStatusLine());
        EntityUtils.consume(response1.getEntity());
    }
    

    非常重要:NTLM 连接是有状态的,只有在与相同的用户身份相关联时才能在上下文之间重复使用。可以在连接HttpClient 实例时关闭连接状态跟踪(如下所示)或在执行上下文中手动设置用户身份(如上所示)。

    CloseableHttpClient client = HttpClientBuilder.create()
            .disableConnectionState()
            .build();
    

    【讨论】:

    • 您创建了一个“上下文”,但您不使用它。我认为正确的是 client.execute(httpGet, context)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-22
    • 1970-01-01
    • 2011-09-26
    • 1970-01-01
    • 1970-01-01
    • 2015-10-19
    • 1970-01-01
    相关资源
    最近更新 更多