当前位置: 首页 > news >正文

聊聊HttpClientBuilder

本文主要研究一下HttpClientBuilder

HttpClientBuilder

httpclient-4.5.10-sources.jar!/org/apache/http/impl/client/HttpClientBuilder.java

public class HttpClientBuilder {public static HttpClientBuilder create() {return new HttpClientBuilder();}protected HttpClientBuilder() {super();}public CloseableHttpClient build() {// Create main request executor// We copy the instance fields to avoid changing them, and rename to avoid accidental use of the wrong versionPublicSuffixMatcher publicSuffixMatcherCopy = this.publicSuffixMatcher;if (publicSuffixMatcherCopy == null) {publicSuffixMatcherCopy = PublicSuffixMatcherLoader.getDefault();}HttpRequestExecutor requestExecCopy = this.requestExec;if (requestExecCopy == null) {requestExecCopy = new HttpRequestExecutor();}HttpClientConnectionManager connManagerCopy = this.connManager;if (connManagerCopy == null) {LayeredConnectionSocketFactory sslSocketFactoryCopy = this.sslSocketFactory;if (sslSocketFactoryCopy == null) {final String[] supportedProtocols = systemProperties ? split(System.getProperty("https.protocols")) : null;final String[] supportedCipherSuites = systemProperties ? split(System.getProperty("https.cipherSuites")) : null;HostnameVerifier hostnameVerifierCopy = this.hostnameVerifier;if (hostnameVerifierCopy == null) {hostnameVerifierCopy = new DefaultHostnameVerifier(publicSuffixMatcherCopy);}if (sslContext != null) {sslSocketFactoryCopy = new SSLConnectionSocketFactory(sslContext, supportedProtocols, supportedCipherSuites, hostnameVerifierCopy);} else {if (systemProperties) {sslSocketFactoryCopy = new SSLConnectionSocketFactory((SSLSocketFactory) SSLSocketFactory.getDefault(),supportedProtocols, supportedCipherSuites, hostnameVerifierCopy);} else {sslSocketFactoryCopy = new SSLConnectionSocketFactory(SSLContexts.createDefault(),hostnameVerifierCopy);}}}@SuppressWarnings("resource")final PoolingHttpClientConnectionManager poolingmgr = new PoolingHttpClientConnectionManager(RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.getSocketFactory()).register("https", sslSocketFactoryCopy).build(),null,null,dnsResolver,connTimeToLive,connTimeToLiveTimeUnit != null ? connTimeToLiveTimeUnit : TimeUnit.MILLISECONDS);if (defaultSocketConfig != null) {poolingmgr.setDefaultSocketConfig(defaultSocketConfig);}if (defaultConnectionConfig != null) {poolingmgr.setDefaultConnectionConfig(defaultConnectionConfig);}if (systemProperties) {String s = System.getProperty("http.keepAlive", "true");if ("true".equalsIgnoreCase(s)) {s = System.getProperty("http.maxConnections", "5");final int max = Integer.parseInt(s);poolingmgr.setDefaultMaxPerRoute(max);poolingmgr.setMaxTotal(2 * max);}}if (maxConnTotal > 0) {poolingmgr.setMaxTotal(maxConnTotal);}if (maxConnPerRoute > 0) {poolingmgr.setDefaultMaxPerRoute(maxConnPerRoute);}connManagerCopy = poolingmgr;}ConnectionReuseStrategy reuseStrategyCopy = this.reuseStrategy;if (reuseStrategyCopy == null) {if (systemProperties) {final String s = System.getProperty("http.keepAlive", "true");if ("true".equalsIgnoreCase(s)) {reuseStrategyCopy = DefaultClientConnectionReuseStrategy.INSTANCE;} else {reuseStrategyCopy = NoConnectionReuseStrategy.INSTANCE;}} else {reuseStrategyCopy = DefaultClientConnectionReuseStrategy.INSTANCE;}}ConnectionKeepAliveStrategy keepAliveStrategyCopy = this.keepAliveStrategy;if (keepAliveStrategyCopy == null) {keepAliveStrategyCopy = DefaultConnectionKeepAliveStrategy.INSTANCE;}AuthenticationStrategy targetAuthStrategyCopy = this.targetAuthStrategy;if (targetAuthStrategyCopy == null) {targetAuthStrategyCopy = TargetAuthenticationStrategy.INSTANCE;}AuthenticationStrategy proxyAuthStrategyCopy = this.proxyAuthStrategy;if (proxyAuthStrategyCopy == null) {proxyAuthStrategyCopy = ProxyAuthenticationStrategy.INSTANCE;}UserTokenHandler userTokenHandlerCopy = this.userTokenHandler;if (userTokenHandlerCopy == null) {if (!connectionStateDisabled) {userTokenHandlerCopy = DefaultUserTokenHandler.INSTANCE;} else {userTokenHandlerCopy = NoopUserTokenHandler.INSTANCE;}}String userAgentCopy = this.userAgent;if (userAgentCopy == null) {if (systemProperties) {userAgentCopy = System.getProperty("http.agent");}if (userAgentCopy == null && !defaultUserAgentDisabled) {userAgentCopy = VersionInfo.getUserAgent("Apache-HttpClient","org.apache.http.client", getClass());}}ClientExecChain execChain = createMainExec(requestExecCopy,connManagerCopy,reuseStrategyCopy,keepAliveStrategyCopy,new ImmutableHttpProcessor(new RequestTargetHost(), new RequestUserAgent(userAgentCopy)),targetAuthStrategyCopy,proxyAuthStrategyCopy,userTokenHandlerCopy);execChain = decorateMainExec(execChain);HttpProcessor httpprocessorCopy = this.httpprocessor;if (httpprocessorCopy == null) {final HttpProcessorBuilder b = HttpProcessorBuilder.create();if (requestFirst != null) {for (final HttpRequestInterceptor i: requestFirst) {b.addFirst(i);}}if (responseFirst != null) {for (final HttpResponseInterceptor i: responseFirst) {b.addFirst(i);}}b.addAll(new RequestDefaultHeaders(defaultHeaders),new RequestContent(),new RequestTargetHost(),new RequestClientConnControl(),new RequestUserAgent(userAgentCopy),new RequestExpectContinue());if (!cookieManagementDisabled) {b.add(new RequestAddCookies());}if (!contentCompressionDisabled) {if (contentDecoderMap != null) {final List<String> encodings = new ArrayList<String>(contentDecoderMap.keySet());Collections.sort(encodings);b.add(new RequestAcceptEncoding(encodings));} else {b.add(new RequestAcceptEncoding());}}if (!authCachingDisabled) {b.add(new RequestAuthCache());}if (!cookieManagementDisabled) {b.add(new ResponseProcessCookies());}if (!contentCompressionDisabled) {if (contentDecoderMap != null) {final RegistryBuilder<InputStreamFactory> b2 = RegistryBuilder.create();for (final Map.Entry<String, InputStreamFactory> entry: contentDecoderMap.entrySet()) {b2.register(entry.getKey(), entry.getValue());}b.add(new ResponseContentEncoding(b2.build()));} else {b.add(new ResponseContentEncoding());}}if (requestLast != null) {for (final HttpRequestInterceptor i: requestLast) {b.addLast(i);}}if (responseLast != null) {for (final HttpResponseInterceptor i: responseLast) {b.addLast(i);}}httpprocessorCopy = b.build();}execChain = new ProtocolExec(execChain, httpprocessorCopy);execChain = decorateProtocolExec(execChain);// Add request retry executor, if not disabledif (!automaticRetriesDisabled) {HttpRequestRetryHandler retryHandlerCopy = this.retryHandler;if (retryHandlerCopy == null) {retryHandlerCopy = DefaultHttpRequestRetryHandler.INSTANCE;}execChain = new RetryExec(execChain, retryHandlerCopy);}HttpRoutePlanner routePlannerCopy = this.routePlanner;if (routePlannerCopy == null) {SchemePortResolver schemePortResolverCopy = this.schemePortResolver;if (schemePortResolverCopy == null) {schemePortResolverCopy = DefaultSchemePortResolver.INSTANCE;}if (proxy != null) {routePlannerCopy = new DefaultProxyRoutePlanner(proxy, schemePortResolverCopy);} else if (systemProperties) {routePlannerCopy = new SystemDefaultRoutePlanner(schemePortResolverCopy, ProxySelector.getDefault());} else {routePlannerCopy = new DefaultRoutePlanner(schemePortResolverCopy);}}// Optionally, add service unavailable retry executorfinal ServiceUnavailableRetryStrategy serviceUnavailStrategyCopy = this.serviceUnavailStrategy;if (serviceUnavailStrategyCopy != null) {execChain = new ServiceUnavailableRetryExec(execChain, serviceUnavailStrategyCopy);}// Add redirect executor, if not disabledif (!redirectHandlingDisabled) {RedirectStrategy redirectStrategyCopy = this.redirectStrategy;if (redirectStrategyCopy == null) {redirectStrategyCopy = DefaultRedirectStrategy.INSTANCE;}execChain = new RedirectExec(execChain, routePlannerCopy, redirectStrategyCopy);}// Optionally, add connection back-off executorif (this.backoffManager != null && this.connectionBackoffStrategy != null) {execChain = new BackoffStrategyExec(execChain, this.connectionBackoffStrategy, this.backoffManager);}Lookup<AuthSchemeProvider> authSchemeRegistryCopy = this.authSchemeRegistry;if (authSchemeRegistryCopy == null) {authSchemeRegistryCopy = RegistryBuilder.<AuthSchemeProvider>create().register(AuthSchemes.BASIC, new BasicSchemeFactory()).register(AuthSchemes.DIGEST, new DigestSchemeFactory()).register(AuthSchemes.NTLM, new NTLMSchemeFactory()).register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory()).register(AuthSchemes.KERBEROS, new KerberosSchemeFactory()).build();}Lookup<CookieSpecProvider> cookieSpecRegistryCopy = this.cookieSpecRegistry;if (cookieSpecRegistryCopy == null) {cookieSpecRegistryCopy = CookieSpecRegistries.createDefault(publicSuffixMatcherCopy);}CookieStore defaultCookieStore = this.cookieStore;if (defaultCookieStore == null) {defaultCookieStore = new BasicCookieStore();}CredentialsProvider defaultCredentialsProvider = this.credentialsProvider;if (defaultCredentialsProvider == null) {if (systemProperties) {defaultCredentialsProvider = new SystemDefaultCredentialsProvider();} else {defaultCredentialsProvider = new BasicCredentialsProvider();}}List<Closeable> closeablesCopy = closeables != null ? new ArrayList<Closeable>(closeables) : null;if (!this.connManagerShared) {if (closeablesCopy == null) {closeablesCopy = new ArrayList<Closeable>(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() {@Overridepublic 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() {@Overridepublic void close() throws IOException {cm.shutdown();}});}return new InternalHttpClient(execChain,connManagerCopy,routePlannerCopy,cookieSpecRegistryCopy,authSchemeRegistryCopy,defaultCookieStore,defaultCredentialsProvider,defaultRequestConfig != null ? defaultRequestConfig : RequestConfig.DEFAULT,closeablesCopy);}
}

HttpClientBuilder提供了静态方法create用于创建builder,其build方法用于创建CloseableHttpClient,它主要是构建ClientExecChain(HttpRequestExecutor、HttpClientConnectionManager、ConnectionReuseStrategy、ConnectionKeepAliveStrategy、AuthenticationStrategy、UserTokenHandler)、ProtocolExec(ClientExecChain、HttpProcessor)、RetryExec(ClientExecChain、HttpRequestRetryHandler)、RedirectExec(HttpRoutePlanner、ServiceUnavailableRetryStrategy、RedirectStrategy)、BackoffStrategyExec;最后构建的是InternalHttpClient

SSLContext

org/apache/http/ssl/SSLContexts.java
对于sslContext不为null的则创建SSLConnectionSocketFactory(sslContext, supportedProtocols, supportedCipherSuites, hostnameVerifierCopy),为null的话,则通过SSLContexts.createDefault()来创建默认的SSLContext

public static SSLContext createDefault() throws SSLInitializationException {try {final SSLContext sslContext = SSLContext.getInstance(SSLContextBuilder.TLS);sslContext.init(null, null, null);return sslContext;} catch (final NoSuchAlgorithmException ex) {throw new SSLInitializationException(ex.getMessage(), ex);} catch (final KeyManagementException ex) {throw new SSLInitializationException(ex.getMessage(), ex);}}

HostnameVerifier

若hostnameVerifier为null,则创建默认的DefaultHostnameVerifier

public DefaultHostnameVerifier(final PublicSuffixMatcher publicSuffixMatcher) {this.publicSuffixMatcher = publicSuffixMatcher;}public DefaultHostnameVerifier() {this(null);}@Overridepublic boolean verify(final String host, final SSLSession session) {try {final Certificate[] certs = session.getPeerCertificates();final X509Certificate x509 = (X509Certificate) certs[0];verify(host, x509);return true;} catch (final SSLException ex) {if (log.isDebugEnabled()) {log.debug(ex.getMessage(), ex);}return false;}}

PoolingHttpClientConnectionManager

org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java

@Contract(threading = ThreadingBehavior.SAFE_CONDITIONAL)
public class PoolingHttpClientConnectionManagerimplements HttpClientConnectionManager, ConnPoolControl<HttpRoute>, Closeable {private final ConfigData configData;private final CPool pool;private final HttpClientConnectionOperator connectionOperator;private final AtomicBoolean isShutDown;public PoolingHttpClientConnectionManager(final HttpClientConnectionOperator httpClientConnectionOperator,final HttpConnectionFactory<HttpRoute, ManagedHttpClientConnection> connFactory,final long timeToLive, final TimeUnit timeUnit) {super();this.configData = new ConfigData();this.pool = new CPool(new InternalConnectionFactory(this.configData, connFactory), 2, 20, timeToLive, timeUnit);this.pool.setValidateAfterInactivity(2000);this.connectionOperator = Args.notNull(httpClientConnectionOperator, "HttpClientConnectionOperator");this.isShutDown = new AtomicBoolean(false);}@Overrideprotected void finalize() throws Throwable {try {shutdown();} finally {super.finalize();}}@Overridepublic void close() {shutdown();}//......
}    

PoolingHttpClientConnectionManager实现了HttpClientConnectionManager、ConnPoolControl、Closeable接口,它使用了CPool作为连接池来管理连接,默认的maxPerRoute为2,maxTotal为20

小结

apache的httpclient的HttpClientBuilder提供了构建CloseableHttpClient的方法,它提供了设置sslContext的方法,如果没有设置则通过SSLContexts.createDefault()来创建默认的SSLContext,若hostnameVerifier为null,则创建默认的DefaultHostnameVerifier,其默认会创建HttpClientConnectionManager,使用的是maxPerRoute为2,maxTotal为20的连接池。

http://www.lryc.cn/news/182012.html

相关文章:

  • MacOS - Sonoma更新了啥
  • C++17中头文件filesystem的使用
  • 「专题速递」数字人直播带货、传统行业数字化升级、远程协作中的低延时视频、地产物业中的通讯终端...
  • PE格式之PE头部
  • SLAM从入门到精通(用python实现机器人运动控制)
  • 接口和抽象类有什么区别?
  • 基于springboot+vue的人事系统
  • 记住这份软件测试八股文还怕不能拿offer?你值得拥有
  • 2023年,在CSDN拥有10000粉丝有多难?
  • C++ -- 学习系列 关联式容器 set 与 map
  • Day 04 python学习笔记
  • Moonbeam Ignite强势回归
  • 【改造后序遍历算法】95. 不同的二叉搜索树 II
  • 栈的基本操作(数据结构)
  • D. Jellyfish and Mex Codeforces Round 901 (Div. 2)
  • 操作系统内存管理相关
  • Sui流动性质押黑客松获胜者公布,助力资产再流通
  • 为什么在使用PageHelper插件时,指定的每页记录数大小失效?显示所有的记录数
  • XML文档基础
  • 软考知识汇总-软件工程
  • 力扣:119. 杨辉三角 II(Python3)
  • 指针笔试题(带解析版)
  • 服务器搭建(TCP套接字)-libevent版(服务端)
  • 斐波那契模型系列【动态规划】
  • 【Java】微服务——Nacos注册中心
  • Redis Cluster Gossip Protocol: PING, PONG, MEET
  • httpserver 下载服务器demo 以及libevent版本的 httpserver
  • 构建强大的RESTful API:@RestController与@Controller的对比与应用
  • 【Java-LangChain:使用 ChatGPT API 搭建系统-10】评估(下)-当不存在一个简单的正确答案时
  • 【微服务的集成测试】python实现-附ChatGPT解析