• 聊聊httpclient的disableConnectionState


    本文主要研究一下httpclient的disableConnectionState

    disableConnectionState

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

        /**
         * 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);
            //...... 	
        }
    
    }        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

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

    execute

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

    			Object userToken = context.getUserToken();
                if (userToken == null) {
                    userToken = userTokenHandler.getUserToken(context);
                    context.setAttribute(HttpClientContext.USER_TOKEN, userToken);
                }
                if (userToken != null) {
                    connHolder.setState(userToken);
                }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

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

    UserTokenHandler

    org/apache/http/client/UserTokenHandler.java

    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);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    UserTokenHandler定义了getUserToken方法

    DefaultUserTokenHandler

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

    @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;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46

    DefaultUserTokenHandler从context中获取userPrincipal

    NoopUserTokenHandler

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

    @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;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    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挂钩起来歧义挺大的

  • 相关阅读:
    .Net 对象生命周期由浅入深2(GC)
    混合动力电动车优化调度与建模(发动机,电机,电池组等组件建模)(Matlab代码实现)
    StringTable/StringPool
    UWB技术在定位系统中的革新应用
    错误关闭idea正在运行的项目
    Golang Sync.WaitGroup 使用及原理
    根据经纬度坐标获得省市区县行政区划城市名称,自建数据库 java python php c# .net 均适用
    数据可视化:动态柱状图
    MySQL流程控制函数
    YYGH-14-监测中心
  • 原文地址:https://blog.csdn.net/hello_ejb3/article/details/134493894