前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >聊聊httpclient的disableConnectionState

聊聊httpclient的disableConnectionState

原创
作者头像
code4it
发布2023-11-19 19:09:13
1740
发布2023-11-19 19:09:13
举报
文章被收录于专栏:码匠的流水账码匠的流水账

本文主要研究一下httpclient的disableConnectionState

disableConnectionState

org/apache/http/impl/client/HttpClientBuilder.java

代码语言:javascript
复制
    /**
     * Disables connection state tracking.
     */
    public final HttpClientBuilder disableConnectionState() {
        connectionStateDisabled = true;
        return this;
    }


    public CloseableHttpClient build() {

    	//......

        UserTokenHandler userTokenHandlerCopy = this.userTokenHandler;
        if (userTokenHandlerCopy == null) {
            if (!connectionStateDisabled) {
                userTokenHandlerCopy = DefaultUserTokenHandler.INSTANCE;
            } else {
                userTokenHandlerCopy = NoopUserTokenHandler.INSTANCE;
            }
        }   

        ClientExecChain execChain = createMainExec(
                requestExecCopy,
                connManagerCopy,
                reuseStrategyCopy,
                keepAliveStrategyCopy,
                new ImmutableHttpProcessor(new RequestTargetHost(), new RequestUserAgent(userAgentCopy)),
                targetAuthStrategyCopy,
                proxyAuthStrategyCopy,
                userTokenHandlerCopy);
        //...... 	
    }

}        

HttpClientBuilder提供了disableConnectionState方法可以设置connectionStateDisabled为true,在该值为true时userTokenHandlerCopy为NoopUserTokenHandler.INSTANCE,而userTokenHandlerCopy是作为创建ClientExecChain(MainClientExec)的参数之一

execute

org/apache/http/impl/execchain/MainClientExec.java

代码语言:javascript
复制
			Object userToken = context.getUserToken();
            if (userToken == null) {
                userToken = userTokenHandler.getUserToken(context);
                context.setAttribute(HttpClientContext.USER_TOKEN, userToken);
            }
            if (userToken != null) {
                connHolder.setState(userToken);
            }

MainClientExec的execute方法会通过context.getUserToken()获取userToken,在userToken为null时会通过serTokenHandler.getUserToken(context)获取userToken然后设置到context中,最后将userToken设置到connHolder的state

UserTokenHandler

org/apache/http/client/UserTokenHandler.java

代码语言:javascript
复制
public interface UserTokenHandler {

    /**
     * The token object returned by this method is expected to uniquely
     * identify the current user if the context is user specific or to be
     * {@code null} if it is not.
     *
     * @param context the execution context
     *
     * @return user token that uniquely identifies the user or
     * {@code null} if the context is not user specific.
     */
    Object getUserToken(HttpContext context);

}

UserTokenHandler定义了getUserToken方法

DefaultUserTokenHandler

org/apache/http/impl/client/DefaultUserTokenHandler.java

代码语言:javascript
复制
@Contract(threading = ThreadingBehavior.IMMUTABLE)
public class DefaultUserTokenHandler implements UserTokenHandler {

    public static final DefaultUserTokenHandler INSTANCE = new DefaultUserTokenHandler();

    @Override
    public Object getUserToken(final HttpContext context) {

        final HttpClientContext clientContext = HttpClientContext.adapt(context);

        Principal userPrincipal = null;

        final AuthState targetAuthState = clientContext.getTargetAuthState();
        if (targetAuthState != null) {
            userPrincipal = getAuthPrincipal(targetAuthState);
            if (userPrincipal == null) {
                final AuthState proxyAuthState = clientContext.getProxyAuthState();
                userPrincipal = getAuthPrincipal(proxyAuthState);
            }
        }

        if (userPrincipal == null) {
            final HttpConnection conn = clientContext.getConnection();
            if (conn.isOpen() && conn instanceof ManagedHttpClientConnection) {
                final SSLSession sslsession = ((ManagedHttpClientConnection) conn).getSSLSession();
                if (sslsession != null) {
                    userPrincipal = sslsession.getLocalPrincipal();
                }
            }
        }

        return userPrincipal;
    }

    private static Principal getAuthPrincipal(final AuthState authState) {
        final AuthScheme scheme = authState.getAuthScheme();
        if (scheme != null && scheme.isComplete() && scheme.isConnectionBased()) {
            final Credentials creds = authState.getCredentials();
            if (creds != null) {
                return creds.getUserPrincipal();
            }
        }
        return null;
    }

}

DefaultUserTokenHandler从context中获取userPrincipal

NoopUserTokenHandler

org/apache/http/impl/client/NoopUserTokenHandler.java

代码语言:javascript
复制
@Contract(threading = ThreadingBehavior.IMMUTABLE)
public class NoopUserTokenHandler implements UserTokenHandler {

    public static final NoopUserTokenHandler INSTANCE = new NoopUserTokenHandler();

    @Override
    public Object getUserToken(final HttpContext context) {
        return null;
    }

}

NoopUserTokenHandler的getUserToken则返回null

小结

httpclient的disableConnectionState设置了ClientExecChain(MainClientExec)的UserTokenHandler为NoopUserTokenHandler,而MainClientExec的execute方法会通过context.getUserToken()获取userToken,在userToken为null时会通过serTokenHandler.getUserToken(context)获取userToken然后设置到context中,最后将userToken设置到connHolder的state。

connHolder的state与userToken挂钩起来歧义挺大的

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • disableConnectionState
  • execute
  • UserTokenHandler
    • DefaultUserTokenHandler
      • NoopUserTokenHandler
      • 小结
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档