httpclient connect連接請(qǐng)求方法源碼解讀
序
本文主要研究一下httpclient的connect
HttpClientConnectionOperator
org/apache/http/conn/HttpClientConnectionOperator.java
public interface HttpClientConnectionOperator {
void connect(
ManagedHttpClientConnection conn,
HttpHost host,
InetSocketAddress localAddress,
int connectTimeout,
SocketConfig socketConfig,
HttpContext context) throws IOException;
void upgrade(
ManagedHttpClientConnection conn,
HttpHost host,
HttpContext context) throws IOException;
}HttpClientConnectionOperator定義了connect及upgrade方法,它有一個(gè)默認(rèn)的實(shí)現(xiàn)類為DefaultHttpClientConnectionOperator
DefaultHttpClientConnectionOperator
org/apache/http/impl/conn/DefaultHttpClientConnectionOperator.java
public class DefaultHttpClientConnectionOperator implements HttpClientConnectionOperator {
static final String SOCKET_FACTORY_REGISTRY = "http.socket-factory-registry";
private final Log log = LogFactory.getLog(getClass());
private final Lookup<ConnectionSocketFactory> socketFactoryRegistry;
private final SchemePortResolver schemePortResolver;
private final DnsResolver dnsResolver;
public DefaultHttpClientConnectionOperator(
final Lookup<ConnectionSocketFactory> socketFactoryRegistry,
final SchemePortResolver schemePortResolver,
final DnsResolver dnsResolver) {
super();
Args.notNull(socketFactoryRegistry, "Socket factory registry");
this.socketFactoryRegistry = socketFactoryRegistry;
this.schemePortResolver = schemePortResolver != null ? schemePortResolver :
DefaultSchemePortResolver.INSTANCE;
this.dnsResolver = dnsResolver != null ? dnsResolver :
SystemDefaultDnsResolver.INSTANCE;
}
//......
public void connect(
final ManagedHttpClientConnection conn,
final HttpHost host,
final InetSocketAddress localAddress,
final int connectTimeout,
final SocketConfig socketConfig,
final HttpContext context) throws IOException {
final Lookup<ConnectionSocketFactory> registry = getSocketFactoryRegistry(context);
final ConnectionSocketFactory sf = registry.lookup(host.getSchemeName());
if (sf == null) {
throw new UnsupportedSchemeException(host.getSchemeName() +
" protocol is not supported");
}
final InetAddress[] addresses = host.getAddress() != null ?
new InetAddress[] { host.getAddress() } : this.dnsResolver.resolve(host.getHostName());
final int port = this.schemePortResolver.resolve(host);
for (int i = 0; i < addresses.length; i++) {
final InetAddress address = addresses[i];
final boolean last = i == addresses.length - 1;
Socket sock = sf.createSocket(context);
sock.setSoTimeout(socketConfig.getSoTimeout());
sock.setReuseAddress(socketConfig.isSoReuseAddress());
sock.setTcpNoDelay(socketConfig.isTcpNoDelay());
sock.setKeepAlive(socketConfig.isSoKeepAlive());
if (socketConfig.getRcvBufSize() > 0) {
sock.setReceiveBufferSize(socketConfig.getRcvBufSize());
}
if (socketConfig.getSndBufSize() > 0) {
sock.setSendBufferSize(socketConfig.getSndBufSize());
}
final int linger = socketConfig.getSoLinger();
if (linger >= 0) {
sock.setSoLinger(true, linger);
}
conn.bind(sock);
final InetSocketAddress remoteAddress = new InetSocketAddress(address, port);
if (this.log.isDebugEnabled()) {
this.log.debug("Connecting to " + remoteAddress);
}
try {
sock = sf.connectSocket(
connectTimeout, sock, host, remoteAddress, localAddress, context);
conn.bind(sock);
if (this.log.isDebugEnabled()) {
this.log.debug("Connection established " + conn);
}
return;
} catch (final SocketTimeoutException ex) {
if (last) {
throw new ConnectTimeoutException(ex, host, addresses);
}
} catch (final ConnectException ex) {
if (last) {
final String msg = ex.getMessage();
throw "Connection timed out".equals(msg)
? new ConnectTimeoutException(ex, host, addresses)
: new HttpHostConnectException(ex, host, addresses);
}
} catch (final NoRouteToHostException ex) {
if (last) {
throw ex;
}
}
if (this.log.isDebugEnabled()) {
this.log.debug("Connect to " + remoteAddress + " timed out. " +
"Connection will be retried using another IP address");
}
}
}
}DefaultHttpClientConnectionOperator的connect先通過(guò)getSocketFactoryRegistry獲取Lookup<ConnectionSocketFactory>,再通過(guò)它獲取ConnectionSocketFactory,之后通過(guò)dnsResolver解析地址,再通過(guò)schemePortResolver解析port,然后通過(guò)ConnectionSocketFactory創(chuàng)建socket,并根據(jù)socketConfig設(shè)置socket的參數(shù),最后執(zhí)行connectSocket,并綁定到conn
connectSocket
org/apache/http/conn/socket/PlainConnectionSocketFactory.java
public class PlainConnectionSocketFactory implements ConnectionSocketFactory {
public static final PlainConnectionSocketFactory INSTANCE = new PlainConnectionSocketFactory();
public static PlainConnectionSocketFactory getSocketFactory() {
return INSTANCE;
}
public PlainConnectionSocketFactory() {
super();
}
@Override
public Socket createSocket(final HttpContext context) throws IOException {
return new Socket();
}
@Override
public Socket connectSocket(
final int connectTimeout,
final Socket socket,
final HttpHost host,
final InetSocketAddress remoteAddress,
final InetSocketAddress localAddress,
final HttpContext context) throws IOException {
final Socket sock = socket != null ? socket : createSocket(context);
if (localAddress != null) {
sock.bind(localAddress);
}
try {
sock.connect(remoteAddress, connectTimeout);
} catch (final IOException ex) {
try {
sock.close();
} catch (final IOException ignore) {
}
throw ex;
}
return sock;
}
}PlainConnectionSocketFactory的createSocket直接new一個(gè)socket,其connectSocket方法則執(zhí)行sock.connect
socketConfig
resolveSocketConfig
org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java
private SocketConfig resolveSocketConfig(final HttpHost host) {
SocketConfig socketConfig = this.configData.getSocketConfig(host);
if (socketConfig == null) {
socketConfig = this.configData.getDefaultSocketConfig();
}
if (socketConfig == null) {
socketConfig = SocketConfig.DEFAULT;
}
return socketConfig;
}PoolingHttpClientConnectionManager的resolveSocketConfig先是從configData根據(jù)指定host獲取socketConfig,若為null則再?gòu)腸onfigData獲取默認(rèn)的socketConfig,若為null則返回默認(rèn)的socketConfig
setSocketConfig
org/apache/http/impl/conn/PoolingHttpClientConnectionManager.java
public void setDefaultSocketConfig(final SocketConfig defaultSocketConfig) {
this.configData.setDefaultSocketConfig(defaultSocketConfig);
}
public void setSocketConfig(final HttpHost host, final SocketConfig socketConfig) {
this.configData.setSocketConfig(host, socketConfig);
}PoolingHttpClientConnectionManager提供了setDefaultSocketConfig、setSocketConfig方法
SocketConfig.DEFAULT
org/apache/http/config/SocketConfig.java
public class SocketConfig implements Cloneable {
public static final SocketConfig DEFAULT = new Builder().build();
//......
public static class Builder {
private int soTimeout;
private boolean soReuseAddress;
private int soLinger;
private boolean soKeepAlive;
private boolean tcpNoDelay;
private int sndBufSize;
private int rcvBufSize;
private int backlogSize;
Builder() {
this.soLinger = -1;
this.tcpNoDelay = true;
}
//......
}
}默認(rèn)的socketConfig,除了tcpNoDelay為true,其他的都為false,然后soLinger為-1
小結(jié)
HttpClientConnectionOperator定義了connect及upgrade方法,它有一個(gè)默認(rèn)的實(shí)現(xiàn)類為DefaultHttpClientConnectionOperator;DefaultHttpClientConnectionOperator的connect先通過(guò)getSocketFactoryRegistry獲取Lookup<ConnectionSocketFactory>,再通過(guò)它獲取ConnectionSocketFactory,之后通過(guò)dnsResolver解析地址,再通過(guò)schemePortResolver解析port,然后通過(guò)ConnectionSocketFactory創(chuàng)建socket,并根據(jù)socketConfig設(shè)置socket的參數(shù),最后執(zhí)行connectSocket,并綁定到conn;默認(rèn)的socketConfig,除了tcpNoDelay為true,其他的都為false,然后soLinger為-1。
以上就是httpclient connect連接請(qǐng)求方法源碼解讀的詳細(xì)內(nèi)容,更多關(guān)于httpclient connect連接請(qǐng)求的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- httpclient getPoolEntryBlocking連接池方法源碼解讀
- httpclient staleConnectionCheckEnabled獲取連接流程解析
- 解讀httpclient的validateAfterInactivity連接池狀態(tài)檢測(cè)
- httpclient的disableConnectionState方法工作流程
- 探索HttpClient中的close方法及其對(duì)連接的影響
- HttpClient的RedirectStrategy重定向處理核心機(jī)制
- HttpClient HttpRoutePlanner接口確定請(qǐng)求目標(biāo)路由
- httpclient ConnectionHolder連接池連接保持源碼解析
相關(guān)文章
重新認(rèn)識(shí)Java中的ThreadLocal
ThreadLocal是JDK包提供的,它提供線程本地變量,如果創(chuàng)建一個(gè)ThreadLocal變量,那么訪問(wèn)這個(gè)變量的每個(gè)線程都會(huì)有這個(gè)變量的一個(gè)副本,在實(shí)際多線程操作的時(shí)候,操作的是自己本地內(nèi)存中的變量,從而規(guī)避了線程安全問(wèn)題2021-05-05
spring 重復(fù)注解和aop攔截的實(shí)現(xiàn)示例
本文主要介紹了spring 重復(fù)注解和aop攔截的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-08-08
解讀Spring配置文件中的property標(biāo)簽中的屬性
這篇文章主要介紹了Spring配置文件中的property標(biāo)簽中的屬性,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
Spring中過(guò)濾器(Filter)和攔截器(Interceptor)到底啥區(qū)別詳解
在Spring框架中過(guò)濾器(Filter)和攔截器(Interceptor)都是用于處理HTTP請(qǐng)求的重要組件,但它們的工作原理和執(zhí)行順序有所不同,這篇文章主要介紹了Spring中過(guò)濾器(Filter)和攔截器(Interceptor)到底啥區(qū)別的相關(guān)資料,需要的朋友可以參考下2026-04-04
springboot打包不同環(huán)境配置以及shell腳本部署的方法
這篇文章主要給大家介紹了關(guān)于springboot打包不同環(huán)境配置以及shell腳本部署的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者使用springboot具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03

