• 聊聊HttpClient的close


    本文主要研究一下HttpClient的close

    CloseableHttpClient

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

    @Contract(threading = ThreadingBehavior.SAFE)
    public abstract class CloseableHttpClient implements HttpClient, Closeable {
    
        @Override
        public  T execute(final HttpHost target, final HttpRequest request,
                final ResponseHandler responseHandler, final HttpContext context)
                throws IOException, ClientProtocolException {
            Args.notNull(responseHandler, "Response handler");
    
            final CloseableHttpResponse response = execute(target, request, context);
            try {
                final T result = responseHandler.handleResponse(response);
                final HttpEntity entity = response.getEntity();
                EntityUtils.consume(entity);
                return result;
            } catch (final ClientProtocolException t) {
                // Try to salvage the underlying connection in case of a protocol exception
                final HttpEntity entity = response.getEntity();
                try {
                    EntityUtils.consume(entity);
                } catch (final Exception t2) {
                    // Log this exception. The original exception is more
                    // important and will be thrown to the caller.
                    this.log.warn("Error consuming content after an exception.", t2);
                }
                throw t;
            } finally {
                response.close();
            }
        }
    
        //......
    }
    
    • 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

    CloseableHttpClient声明实现HttpClient, Closeable接口

    InternalHttpClient

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

    @Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL)
    @SuppressWarnings("deprecation")
    class InternalHttpClient extends CloseableHttpClient implements Configurable {
    
        private final Log log = LogFactory.getLog(getClass());
    
        private final ClientExecChain execChain;
        private final HttpClientConnectionManager connManager;
        private final HttpRoutePlanner routePlanner;
        private final Lookup cookieSpecRegistry;
        private final Lookup authSchemeRegistry;
        private final CookieStore cookieStore;
        private final CredentialsProvider credentialsProvider;
        private final RequestConfig defaultConfig;
        private final List closeables;
    
        public InternalHttpClient(
                final ClientExecChain execChain,
                final HttpClientConnectionManager connManager,
                final HttpRoutePlanner routePlanner,
                final Lookup cookieSpecRegistry,
                final Lookup authSchemeRegistry,
                final CookieStore cookieStore,
                final CredentialsProvider credentialsProvider,
                final RequestConfig defaultConfig,
                final List closeables) {
            super();
            Args.notNull(execChain, "HTTP client exec chain");
            Args.notNull(connManager, "HTTP connection manager");
            Args.notNull(routePlanner, "HTTP route planner");
            this.execChain = execChain;
            this.connManager = connManager;
            this.routePlanner = routePlanner;
            this.cookieSpecRegistry = cookieSpecRegistry;
            this.authSchemeRegistry = authSchemeRegistry;
            this.cookieStore = cookieStore;
            this.credentialsProvider = credentialsProvider;
            this.defaultConfig = defaultConfig;
            this.closeables = closeables;
        }
    
        //......
    
        @Override
        public void close() {
            if (this.closeables != null) {
                for (final Closeable closeable: this.closeables) {
                    try {
                        closeable.close();
                    } catch (final IOException ex) {
                        this.log.error(ex.getMessage(), ex);
                    }
                }
            }
        }    
    }    
    
    • 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
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    InternalHttpClient继承了CloseableHttpClient,其构造器要求传入closeables,它实现了close方法,它主要是遍历closeables,挨个执行close

    HttpClientBuilder

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

    public class HttpClientBuilder {
    
    	private List closeables;
    
    	private boolean connManagerShared;
    
    	//......
    
        /**
         * For internal use.
         */
        protected void addCloseable(final Closeable closeable) {
            if (closeable == null) {
                return;
            }
            if (closeables == null) {
                closeables = new ArrayList();
            }
            closeables.add(closeable);
        }
    
        public CloseableHttpClient build() {
    
        	//......
    
            List closeablesCopy = closeables != null ? new ArrayList(closeables) : null;
            if (!this.connManagerShared) {
                if (closeablesCopy == null) {
                    closeablesCopy = new ArrayList(1);
                }
                final HttpClientConnectionManager cm = connManagerCopy;
    
                if (evictExpiredConnections || evictIdleConnections) {
                    final IdleConnectionEvictor connectionEvictor = new IdleConnectionEvictor(cm,
                            maxIdleTime > 0 ? maxIdleTime : 10, maxIdleTimeUnit != null ? maxIdleTimeUnit : TimeUnit.SECONDS,
                            maxIdleTime, maxIdleTimeUnit);
                    closeablesCopy.add(new Closeable() {
    
                        @Override
                        public void close() throws IOException {
                            connectionEvictor.shutdown();
                            try {
                                connectionEvictor.awaitTermination(1L, TimeUnit.SECONDS);
                            } catch (final InterruptedException interrupted) {
                                Thread.currentThread().interrupt();
                            }
                        }
    
                    });
                    connectionEvictor.start();
                }
                closeablesCopy.add(new Closeable() {
    
                    @Override
                    public void close() throws IOException {
                        cm.shutdown();
                    }
    
                });
            }
    
            //......
    
            return new InternalHttpClient(
                    execChain,
                    connManagerCopy,
                    routePlannerCopy,
                    cookieSpecRegistryCopy,
                    authSchemeRegistryCopy,
                    defaultCookieStore,
                    defaultCredentialsProvider,
                    defaultRequestConfig != null ? defaultRequestConfig : RequestConfig.DEFAULT,
                    closeablesCopy);
        }
    }    
    
    • 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
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75

    HttpClientBuilder定义了addCloseable方法用于添加closeable,不过是protected;而build方法在connManagerShared参数为false的时候(默认)会创建closeablesCopy,创建Closeable去关闭HttpClientConnectionManager并添加到closeablesCopy中;

    在开启evictExpiredConnections或者evictIdleConnections的时候会创建IdleConnectionEvictor,然后创建关闭connectionEvictor的Closeable添加到closeablesCopy中

    最后将这些closeablesCopy传递给InternalHttpClient的构造器

    小结

    HttpClient(CloseableHttpClient)的close方法会关闭一系列的Closeable,这些Closeable在HttpClientBuilder的build方法会构建好然后传递给InternalHttpClient;默认情况下这些closeable包括HttpClientConnectionManager的关闭、IdleConnectionEvictor的关闭。

  • 相关阅读:
    揭秘OLED透明拼接屏的参数规格:分辨率、亮度与透明度全解析
    第十四届蓝桥杯大赛软件赛决赛 C/C++ 大学 B 组 试题 E: 数三角
    爬虫模块—每日行情数据/交易日期/公司信息获取(01)
    比特币势在解决法币阻碍进步的问题
    C语言 实现贪吃蛇 | 十分钟入门案例 | 初学者案例 | 附带设计思路 + 代码 + 图文分析
    C语言:文件操作
    S0002-HomeBrew基础入门
    构建网络下载器:Wt库指南让您轻松获取豆瓣网的美图
    linux查看各个目录占用磁盘的大小&清理nohup.out日志
    Codeforces Round #814 (Div. 2)
  • 原文地址:https://blog.csdn.net/hello_ejb3/article/details/134065215