/*
* Copyright (C) 2012 Square, Inc.
*照猫画虎 依葫芦画瓢 个人能力理解解释,老外属性和方法不写功能注释,这样很不爽
这里面是不是用到了一个设计模式叫构建者?
(建议大家学习设计模式可以先学习概念然后再到实际开源项目中去寻找具体的例子,然后再结合设计模式的概
念来翻来覆去的比较,就像烙大饼一样,翻来翻去,否则光烙一面大饼就烙糊了O(∩_∩)O哈哈~)
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package okhttp3;
import java.net.MalformedURLException;
import java.net.Proxy;//代理
import java.net.ProxySelector;//代理选择器
import java.net.Socket;//socket
import java.net.UnknownHostException;//位置的主机异常
import java.security.GeneralSecurityException;//生成安全异常?
import java.security.KeyStore;//秘钥存储?
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;//随机数
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;//时间单位
import javax.annotation.Nullable;
import javax.net.SocketFactory;//socket工厂
import javax.net.ssl.HostnameVerifier;//主机名校验?
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import okhttp3.internal.Internal;
import okhttp3.internal.Util;
import okhttp3.internal.cache.InternalCache;//内部高速缓存
import okhttp3.internal.connection.RealConnection;//重新连接?
import okhttp3.internal.connection.RouteDatabase;//路由数据库
import okhttp3.internal.connection.StreamAllocation;
import okhttp3.internal.platform.Platform;//平台
import okhttp3.internal.tls.CertificateChainCleaner;
import okhttp3.internal.tls.OkHostnameVerifier;
import okhttp3.internal.ws.RealWebSocket;
/**
* Factory for {@linkplain Call calls}, which can be used to send HTTP requests and read their
* responses.
*
* <h3>OkHttpClients should be shared</h3>
*
* <p>OkHttp performs best when you create a single {@code OkHttpClient} instance and reuse it for
* all of your HTTP calls. This is because each client holds its own connection pool and thread
* pools. Reusing connections and threads reduces latency and saves memory. Conversely, creating a
* client for each request wastes resources on idle pools.
*
* <p>Use {@code new OkHttpClient()} to create a shared instance with the default settings:
* <pre> {@code
*
* // The singleton HTTP client.
* public final OkHttpClient client = new OkHttpClient();
* }</pre>
*
* <p>Or use {@code new OkHttpClient.Builder()} to create a shared instance with custom settings:
* <pre> {@code
*
* // The singleton HTTP client.
* public final OkHttpClient client = new OkHttpClient.Builder()
* .addInterceptor(new HttpLoggingInterceptor())
* .cache(new Cache(cacheDir, cacheSize))
* .build();
* }</pre>
*
* <h3>Customize your client with newBuilder()</h3>
*
* <p>You can customize a shared OkHttpClient instance with {@link #newBuilder()}. This builds a
* client that shares the same connection pool, thread pools, and configuration. Use the builder
* methods to configure the derived client for a specific purpose.
*
* <p>This example shows a call with a short 500 millisecond timeout: <pre> {@code
*
* OkHttpClient eagerClient = client.newBuilder()
* .readTimeout(500, TimeUnit.MILLISECONDS)
* .build();
* Response response = eagerClient.newCall(request).execute();
* }</pre>
*
* <h3>Shutdown isn't necessary</h3>
*
* <p>The threads and connections that are held will be released automatically if they remain idle.
* But if you are writing a application that needs to aggressively release unused resources you may
* do so.
*
* <p>Shutdown the dispatcher's executor service with {@link ExecutorService#shutdown shutdown()}.
* This will also cause future calls to the client to be rejected. <pre> {@code
*
* client.dispatcher().executorService().shutdown();
* }</pre>
*
* <p>Clear the connection pool with {@link ConnectionPool#evictAll() evictAll()}. Note that the
* connection pool's daemon thread may not exit immediately. <pre> {@code
*
* client.connectionPool().evictAll();
* }</pre>
*
* <p>If your client has a cache, call {@link Cache#close close()}. Note that it is an error to
* create calls against a cache that is closed, and doing so will cause the call to crash.
* <pre> {@code
*
* client.cache().close();
* }</pre>
*
* <p>OkHttp also uses daemon threads for HTTP/2 connections. These will exit automatically if they
* remain idle.
*/
public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory {
static final List<Protocol> DEFAULT_PROTOCOLS = Util.immutableList(
Protocol.HTTP_2, Protocol.HTTP_1_1);
static final List<ConnectionSpec> DEFAULT_CONNECTION_SPECS = Util.immutableList(
ConnectionSpec.MODERN_TLS, ConnectionSpec.CLEARTEXT);
//静态代码块
static {
Internal.instance = new Internal() {
@Override public void addLenient(Headers.Builder builder, String line) {
builder.addLenient(line);
}
@Override public void addLenient(Headers.Builder builder, String name, String value) {
builder.addLenient(name, value);
}
@Override public void setCache(Builder builder, InternalCache internalCache) {
builder.setInternalCache(internalCache);
}
@Override public boolean connectionBecameIdle(
ConnectionPool pool, RealConnection connection) {
return pool.connectionBecameIdle(connection);
}
@Override public RealConnection get(ConnectionPool pool, Address address,
StreamAllocation streamAllocation, Route route) {
return pool.get(address, streamAllocation, route);
}
@Override public boolean equalsNonHost(Address a, Address b) {
return a.equalsNonHost(b);
}
@Override public Socket deduplicate(
ConnectionPool pool, Address address, StreamAllocation streamAllocation) {
return pool.deduplicate(address, streamAllocation);
}
@Override public void put(ConnectionPool pool, RealConnection connection) {
pool.put(connection);
}
@Override public RouteDatabase routeDatabase(ConnectionPool connectionPool) {
return connectionPool.routeDatabase;
}
@Override public int code(Response.Builder responseBuilder) {
return responseBuilder.code;
}
@Override
public void apply(ConnectionSpec tlsConfiguration, SSLSocket sslSocket, boolean isFallback) {
tlsConfiguration.apply(sslSocket, isFallback);
}
@Override public HttpUrl getHttpUrlChecked(String url)
throws MalformedURLException, UnknownHostException {
return HttpUrl.getChecked(url);
}
@Override public StreamAllocation streamAllocation(Call call) {
return ((RealCall) call).streamAllocation();
}
@Override public Call newWebSocketCall(OkHttpClient client, Request originalRequest) {
return new RealCall(client, originalRequest, true);
}
};
}
final Dispatcher dispatcher;
final @Nullable Proxy proxy;
final List<Protocol> protocols;//协议列表?
final List<ConnectionSpec> connectionSpecs;
final List<Interceptor> interceptors;
final List<Interceptor> networkInterceptors;
final EventListener.Factory eventListenerFactory;
final ProxySelector proxySelector;
final CookieJar cookieJar;
final @Nullable Cache cache;
final @Nullable InternalCache internalCache;
final SocketFactory socketFactory;//socket工厂?
final @Nullable SSLSocketFactory sslSocketFactory;
final @Nullable CertificateChainCleaner certificateChainCleaner;
final HostnameVerifier hostnameVerifier;
final CertificatePinner certificatePinner;
final Authenticator proxyAuthenticator;
final Authenticator authenticator;
final ConnectionPool connectionPool;//连接池?
final Dns dns;
final boolean followSslRedirects;
final boolean followRedirects;
final boolean retryOnConnectionFailure;//连接失败重试?
final int connectTimeout;//连接超时?
final int readTimeout;//读取超时?
final int writeTimeout;//写超时?
final int pingInterval;
public OkHttpClient() {
this(new Builder());
}
//构建者模式的适用场景为:构造函数中有很多很多参数,有些是必须有的,有些是非必须的,这样实例化是一件令人头疼的事情
//如下使用的构建者模式,构造函数里需要用到很多的参数,但是参数的实例化交给了Builder这个内部类去实例化
OkHttpClient(Builder builder) {
this.dispatcher = builder.dispatcher;
this.proxy = builder.proxy;
this.protocols = builder.protocols;
this.connectionSpecs = builder.connectionSpecs;
this.interceptors = Util.immutableList(builder.interceptors);
this.networkInterceptors = Util.immutableList(builder.networkInterceptors);
this.eventListenerFactory = builder.eventListenerFactory;
this.proxySelector = builder.proxySelector;
this.cookieJar = builder.cookieJar;
this.cache = builder.cache;
this.internalCache = builder.internalCache;
this.socketFactory = builder.socketFactory;
boolean isTLS = false;
for (ConnectionSpec spec : connectionSpecs) {
isTLS = isTLS || spec.isTls();
}
if (builder.sslSocketFactory != null || !isTLS) {
this.sslSocketFactory = builder.sslSocketFactory;
this.certificateChainCleaner = builder.certificateChainCleaner;
} else {
X509TrustManager trustManager = systemDefaultTrustManager();
this.sslSocketFactory = systemDefaultSslSocketFactory(trustManager);
this.certificateChainCleaner = CertificateChainCleaner.get(trustManager);
}
this.hostnameVerifier = builder.hostnameVerifier;
this.certificatePinner = builder.certificatePinner.withCertificateChainCleaner(
certificateChainCleaner);
this.proxyAuthenticator = builder.proxyAuthenticator;
this.authenticator = builder.authenticator;
this.connectionPool = builder.connectionPool;
this.dns = builder.dns;
this.followSslRedirects = builder.followSslRedirects;
this.followRedirects = builder.followRedirects;
this.retryOnConnectionFailure = builder.retryOnConnectionFailure;
this.connectTimeout = builder.connectTimeout;
this.readTimeout = builder.readTimeout;
this.writeTimeout = builder.writeTimeout;
this.pingInterval = builder.pingInterval;
}
private X509TrustManager systemDefaultTrustManager() {
try {
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException("Unexpected default trust managers:"
+ Arrays.toString(trustManagers));
}
return (X509TrustManager) trustManagers[0];
} catch (GeneralSecurityException e) {
throw new AssertionError(); // The system has no TLS. Just give up.
}
}
private SSLSocketFactory systemDefaultSslSocketFactory(X509TrustManager trustManager) {
try {
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[] { trustManager }, null);
return sslContext.getSocketFactory();
} catch (GeneralSecurityException e) {
throw new AssertionError(); // The system has no TLS. Just give up.
}
}
/**返回连接超时,单位毫秒? Default connect timeout (in milliseconds). */
public int connectTimeoutMillis() {
return connectTimeout;
}
/**返回读取超时,单位毫秒? Default read timeout (in milliseconds). */
public int readTimeoutMillis() {
return readTimeout;
}
/**返回写超时,单位毫秒 Default write timeout (in milliseconds). */
public int writeTimeoutMillis() {
return writeTimeout;
}
/** Web socket ping interval (in milliseconds). */
public int pingIntervalMillis() {
return pingInterval;
}
public Proxy proxy() {
return proxy;
}
public ProxySelector proxySelector() {
return proxySelector;
}
public CookieJar cookieJar() {
return cookieJar;
}
public Cache cache() {
return cache;
}
InternalCache internalCache() {
return cache != null ? cache.internalCache : internalCache;
}
public Dns dns() {
return dns;
}
public SocketFactory socketFactory() {
return socketFactory;
}
public SSLSocketFactory sslSocketFactory() {
return sslSocketFactory;
}
public HostnameVerifier hostnameVerifier() {
return hostnameVerifier;
}
public CertificatePinner certificatePinner() {
return certificatePinner;
}
public Authenticator authenticator() {
return authenticator;
}
public Authenticator proxyAuthenticator() {
return proxyAuthenticator;
}
//连接池
public ConnectionPool connectionPool() {
return connectionPool;
}
public boolean followSslRedirects() {
return followSslRedirects;
}
public boolean followRedirects() {
return followRedirects;
}
//连接失败重试
public boolean retryOnConnectionFailure() {
return retryOnConnectionFailure;
}
public Dispatcher dispatcher() {
return dispatcher;
}
//返回协议列表
public List<Protocol> protocols() {
return protocols;
}
public List<ConnectionSpec> connectionSpecs() {
return connectionSpecs;
}
/**
* Returns an immutable list of interceptors that observe the full span of each call: from before
* the connection is established (if any) until after the response source is selected (either the
* origin server, cache, or both).
*/
public List<Interceptor> interceptors() {
return interceptors;
}
/**
* Returns an immutable list of interceptors that observe a single network request and response.
* These interceptors must call {@link Interceptor.Chain#proceed} exactly once: it is an error for
* a network interceptor to short-circuit or repeat a network request.
*/
public List<Interceptor> networkInterceptors() {
return networkInterceptors;
}
// TODO(jwilson): make this public after the 3.8 release.
/*public*/ EventListener.Factory eventListenerFactory() {
return eventListenerFactory;
}
/**
* Prepares the {@code request} to be executed at some point in the future.
*/
@Override public Call newCall(Request request) {
return new RealCall(this, request, false /* for web socket */);
}
/**
* Uses {@code request} to connect a new web socket.
*/
@Override public WebSocket newWebSocket(Request request, WebSocketListener listener) {
RealWebSocket webSocket = new RealWebSocket(request, listener, new Random());
webSocket.connect(this);
return webSocket;
}
public Builder newBuilder() {
return new Builder(this);
}
//静态内部类Builder
public static final class Builder {
Dispatcher dispatcher;
@Nullable Proxy proxy;
List<Protocol> protocols;//协议列表
List<ConnectionSpec> connectionSpecs;
final List<Interceptor> interceptors = new ArrayList<>();
final List<Interceptor> networkInterceptors = new ArrayList<>();
EventListener.Factory eventListenerFactory;
ProxySelector proxySelector;
CookieJar cookieJar;
@Nullable Cache cache;
@Nullable InternalCache internalCache;
SocketFactory socketFactory;//socket工厂
@Nullable SSLSocketFactory sslSocketFactory;
@Nullable CertificateChainCleaner certificateChainCleaner;
HostnameVerifier hostnameVerifier;
CertificatePinner certificatePinner;
Authenticator proxyAuthenticator;
Authenticator authenticator;
ConnectionPool connectionPool;
Dns dns;
boolean followSslRedirects;
boolean followRedirects;
boolean retryOnConnectionFailure;
int connectTimeout;//连接超时
int readTimeout;//读取超时
int writeTimeout;//写超时
int pingInterval;
//无参数构造函数,默认值
//由构建者来完成很多参数的实例化工作
public Builder() {
dispatcher = new Dispatcher();
protocols = DEFAULT_PROTOCOLS;
connectionSpecs = DEFAULT_CONNECTION_SPECS;
eventListenerFactory = EventListener.factory(EventListener.NONE);
proxySelector = ProxySelector.getDefault();
cookieJar = CookieJar.NO_COOKIES;
socketFactory = SocketFactory.getDefault();//socket工厂
hostnameVerifier = OkHostnameVerifier.INSTANCE;
certificatePinner = CertificatePinner.DEFAULT;
proxyAuthenticator = Authenticator.NONE;
authenticator = Authenticator.NONE;
connectionPool = new ConnectionPool();//初始化连接池
dns = Dns.SYSTEM;
followSslRedirects = true;
followRedirects = true;
retryOnConnectionFailure = true;
connectTimeout = 10_000;//?这里是什么情况,下横线代表什么?
readTimeout = 10_000;
writeTimeout = 10_000;
pingInterval = 0;
}
//有参数构造函数
Builder(OkHttpClient okHttpClient) {
this.dispatcher = okHttpClient.dispatcher;
this.proxy = okHttpClient.proxy;
this.protocols = okHttpClient.protocols;
this.connectionSpecs = okHttpClient.connectionSpecs;
this.interceptors.addAll(okHttpClient.interceptors);
this.networkInterceptors.addAll(okHttpClient.networkInterceptors);
this.eventListenerFactory = okHttpClient.eventListenerFactory;
this.proxySelector = okHttpClient.proxySelector;
this.cookieJar = okHttpClient.cookieJar;
this.internalCache = okHttpClient.internalCache;
this.cache = okHttpClient.cache;
this.socketFactory = okHttpClient.socketFactory;
this.sslSocketFactory = okHttpClient.sslSocketFactory;
this.certificateChainCleaner = okHttpClient.certificateChainCleaner;
this.hostnameVerifier = okHttpClient.hostnameVerifier;
this.certificatePinner = okHttpClient.certificatePinner;
this.proxyAuthenticator = okHttpClient.proxyAuthenticator;
this.authenticator = okHttpClient.authenticator;
this.connectionPool = okHttpClient.connectionPool;
this.dns = okHttpClient.dns;
this.followSslRedirects = okHttpClient.followSslRedirects;
this.followRedirects = okHttpClient.followRedirects;
this.retryOnConnectionFailure = okHttpClient.retryOnConnectionFailure;
this.connectTimeout = okHttpClient.connectTimeout;
this.readTimeout = okHttpClient.readTimeout;
this.writeTimeout = okHttpClient.writeTimeout;
this.pingInterval = okHttpClient.pingInterval;
}
/**
设置连接超时时间
* Sets the default connect timeout for new connections. A value of 0 means no timeout,
* otherwise values must be between 1 and {@link Integer#MAX_VALUE} when converted to
* milliseconds.
*/
public Builder connectTimeout(long timeout, TimeUnit unit) {
connectTimeout = checkDuration("timeout", timeout, unit);
return this;
}
/**
设置读取超时时间
* Sets the default read timeout for new connections. A value of 0 means no timeout, otherwise
* values must be between 1 and {@link Integer#MAX_VALUE} when converted to milliseconds.
*/
public Builder readTimeout(long timeout, TimeUnit unit) {
readTimeout = checkDuration("timeout", timeout, unit);
return this;
}
/**
设置写超时时间
* Sets the default write timeout for new connections. A value of 0 means no timeout, otherwise
* values must be between 1 and {@link Integer#MAX_VALUE} when converted to milliseconds.
*/
public Builder writeTimeout(long timeout, TimeUnit unit) {
writeTimeout = checkDuration("timeout", timeout, unit);
return this;
}
/**
* Sets the interval between web socket pings initiated by this client. Use this to
* automatically send web socket ping frames until either the web socket fails or it is closed.
* This keeps the connection alive and may detect connectivity failures early. No timeouts are
* enforced on the acknowledging pongs.
*
* <p>The default value of 0 disables client-initiated pings.
*/
public Builder pingInterval(long interval, TimeUnit unit) {
pingInterval = checkDuration("interval", interval, unit);
return this;
}
private static int checkDuration(String name, long duration, TimeUnit unit) {
if (duration < 0) throw new IllegalArgumentException(name + " < 0");
if (unit == null) throw new NullPointerException("unit == null");
long millis = unit.toMillis(duration);
if (millis > Integer.MAX_VALUE) throw new IllegalArgumentException(name + " too large.");
if (millis == 0 && duration > 0) throw new IllegalArgumentException(name + " too small.");
return (int) millis;
}
/**
* Sets the HTTP proxy that will be used by connections created by this client. This takes
* precedence over {@link #proxySelector}, which is only honored when this proxy is null (which
* it is by default). To disable proxy use completely, call {@code setProxy(Proxy.NO_PROXY)}.
*/
public Builder proxy(@Nullable Proxy proxy) {
this.proxy = proxy;
return this;
}
/**
* Sets the proxy selection policy to be used if no {@link #proxy proxy} is specified
* explicitly. The proxy selector may return multiple proxies; in that case they will be tried
* in sequence until a successful connection is established.
*
* <p>If unset, the {@link ProxySelector#getDefault() system-wide default} proxy selector will
* be used.
*/
public Builder proxySelector(ProxySelector proxySelector) {
this.proxySelector = proxySelector;
return this;
}
/**
* Sets the handler that can accept cookies from incoming HTTP responses and provides cookies to
* outgoing HTTP requests.
*
* <p>If unset, {@linkplain CookieJar#NO_COOKIES no cookies} will be accepted nor provided.
*/
public Builder cookieJar(CookieJar cookieJar) {
if (cookieJar == null) throw new NullPointerException("cookieJar == null");
this.cookieJar = cookieJar;
return this;
}
/** Sets the response cache to be used to read and write cached responses. */
void setInternalCache(@Nullable InternalCache internalCache) {
this.internalCache = internalCache;
this.cache = null;
}
/** Sets the response cache to be used to read and write cached responses. */
public Builder cache(@Nullable Cache cache) {
this.cache = cache;
this.internalCache = null;
return this;
}
/**
设置DNS服务,用来为服务器寻找IP地址
* Sets the DNS service used to lookup IP addresses for hostnames.
*
* <p>If unset, the {@link Dns#SYSTEM system-wide default} DNS will be used.
*/
public Builder dns(Dns dns) {
if (dns == null) throw new NullPointerException("dns == null");
this.dns = dns;
return this;
}
/**
设置socket工厂
* Sets the socket factory used to create connections. OkHttp only uses the parameterless {@link
* SocketFactory#createSocket() createSocket()} method to create unconnected sockets. Overriding
* this method, e. g., allows the socket to be bound to a specific local address.
*
* <p>If unset, the {@link SocketFactory#getDefault() system-wide default} socket factory will
* be used.
*/
public Builder socketFactory(SocketFactory socketFactory) {
if (socketFactory == null) throw new NullPointerException("socketFactory == null");
this.socketFactory = socketFactory;
return this;
}
/**
设置socket工厂
* Sets the socket factory used to secure HTTPS connections. If unset, the system default will
* be used.
*
* @deprecated {@code SSLSocketFactory} does not expose its {@link X509TrustManager}, which is
* a field that OkHttp needs to build a clean certificate chain. This method instead must
* use reflection to extract the trust manager. Applications should prefer to call {@link
* #sslSocketFactory(SSLSocketFactory, X509TrustManager)}, which avoids such reflection.
*/
public Builder sslSocketFactory(SSLSocketFactory sslSocketFactory) {
if (sslSocketFactory == null) throw new NullPointerException("sslSocketFactory == null");
X509TrustManager trustManager = Platform.get().trustManager(sslSocketFactory);
if (trustManager == null) {
throw new IllegalStateException("Unable to extract the trust manager on " + Platform.get()
+ ", sslSocketFactory is " + sslSocketFactory.getClass());
}
this.sslSocketFactory = sslSocketFactory;
this.certificateChainCleaner = CertificateChainCleaner.get(trustManager);
return this;
}
/**
设置socket工厂
* Sets the socket factory and trust manager used to secure HTTPS connections. If unset, the
* system defaults will be used.
*
* <p>Most applications should not call this method, and instead use the system defaults. Those
* classes include special optimizations that can be lost if the implementations are decorated.
*
* <p>If necessary, you can create and configure the defaults yourself with the following code:
*
* <pre> {@code
*
* TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
* TrustManagerFactory.getDefaultAlgorithm());
* trustManagerFactory.init((KeyStore) null);
* TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
* if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
* throw new IllegalStateException("Unexpected default trust managers:"
* + Arrays.toString(trustManagers));
* }
* X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
*
* SSLContext sslContext = SSLContext.getInstance("TLS");
* sslContext.init(null, new TrustManager[] { trustManager }, null);
* SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
*
* OkHttpClient client = new OkHttpClient.Builder()
* .sslSocketFactory(sslSocketFactory, trustManager);
* .build();
* }</pre>
*/
public Builder sslSocketFactory(
SSLSocketFactory sslSocketFactory, X509TrustManager trustManager) {
if (sslSocketFactory == null) throw new NullPointerException("sslSocketFactory == null");
if (trustManager == null) throw new NullPointerException("trustManager == null");
this.sslSocketFactory = sslSocketFactory;
this.certificateChainCleaner = CertificateChainCleaner.get(trustManager);
return this;
}
/**
* Sets the verifier used to confirm that response certificates apply to requested hostnames for
* HTTPS connections.
*
* <p>If unset, a default hostname verifier will be used.
*/
public Builder hostnameVerifier(HostnameVerifier hostnameVerifier) {
if (hostnameVerifier == null) throw new NullPointerException("hostnameVerifier == null");
this.hostnameVerifier = hostnameVerifier;
return this;
}
/**
* Sets the certificate pinner that constrains which certificates are trusted. By default HTTPS
* connections rely on only the {@link #sslSocketFactory SSL socket factory} to establish trust.
* Pinning certificates avoids the need to trust certificate authorities.
*/
public Builder certificatePinner(CertificatePinner certificatePinner) {
if (certificatePinner == null) throw new NullPointerException("certificatePinner == null");
this.certificatePinner = certificatePinner;
return this;
}
/**
* Sets the authenticator used to respond to challenges from origin servers. Use {@link
* #proxyAuthenticator} to set the authenticator for proxy servers.
*
* <p>If unset, the {@linkplain Authenticator#NONE no authentication will be attempted}.
*/
public Builder authenticator(Authenticator authenticator) {
if (authenticator == null) throw new NullPointerException("authenticator == null");
this.authenticator = authenticator;
return this;
}
/**
* Sets the authenticator used to respond to challenges from proxy servers. Use {@link
* #authenticator} to set the authenticator for origin servers.
*
* <p>If unset, the {@linkplain Authenticator#NONE no authentication will be attempted}.
*/
public Builder proxyAuthenticator(Authenticator proxyAuthenticator) {
if (proxyAuthenticator == null) throw new NullPointerException("proxyAuthenticator == null");
this.proxyAuthenticator = proxyAuthenticator;
return this;
}
/**
设置连接池
* Sets the connection pool used to recycle HTTP and HTTPS connections.
*
* <p>If unset, a new connection pool will be used.
*/
public Builder connectionPool(ConnectionPool connectionPool) {
if (connectionPool == null) throw new NullPointerException("connectionPool == null");
this.connectionPool = connectionPool;
return this;
}
/**
* Configure this client to follow redirects from HTTPS to HTTP and from HTTP to HTTPS.
*
* <p>If unset, protocol redirects will be followed. This is different than the built-in {@code
* HttpURLConnection}'s default.
*/
public Builder followSslRedirects(boolean followProtocolRedirects) {
this.followSslRedirects = followProtocolRedirects;
return this;
}
/** Configure this client to follow redirects. If unset, redirects will be followed. */
public Builder followRedirects(boolean followRedirects) {
this.followRedirects = followRedirects;
return this;
}
/**
设置是否连接失败后重试连接
* Configure this client to retry or not when a connectivity problem is encountered. By default,
* this client silently recovers from the following problems:
*
* <ul>
* <li><strong>Unreachable IP addresses.</strong> If the URL's host has multiple IP addresses,
* failure to reach any individual IP address doesn't fail the overall request. This can
* increase availability of multi-homed services.
* <li><strong>Stale pooled connections.</strong> The {@link ConnectionPool} reuses sockets
* to decrease request latency, but these connections will occasionally time out.
* <li><strong>Unreachable proxy servers.</strong> A {@link ProxySelector} can be used to
* attempt multiple proxy servers in sequence, eventually falling back to a direct
* connection.
* </ul>
*
* Set this to false to avoid retrying requests when doing so is destructive. In this case the
* calling application should do its own recovery of connectivity failures.
*/
public Builder retryOnConnectionFailure(boolean retryOnConnectionFailure) {
this.retryOnConnectionFailure = retryOnConnectionFailure;
return this;
}
/**
* Sets the dispatcher used to set policy and execute asynchronous requests. Must not be null.
*/
public Builder dispatcher(Dispatcher dispatcher) {
if (dispatcher == null) throw new IllegalArgumentException("dispatcher == null");
this.dispatcher = dispatcher;
return this;
}
/**
* Configure the protocols used by this client to communicate with remote servers. By default
* this client will prefer the most efficient transport available, falling back to more
* ubiquitous protocols. Applications should only call this method to avoid specific
* compatibility problems, such as web servers that behave incorrectly when HTTP/2 is enabled.
*
* <p>The following protocols are currently supported:
*
* <ul>
* <li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616.html">http/1.1</a>
* <li><a href="http://tools.ietf.org/html/draft-ietf-httpbis-http2-17">h2</a>
* </ul>
*
* <p><strong>This is an evolving set.</strong> Future releases include support for transitional
* protocols. The http/1.1 transport will never be dropped.
*
* <p>If multiple protocols are specified, <a
* href="http://tools.ietf.org/html/draft-ietf-tls-applayerprotoneg">ALPN</a> will be used to
* negotiate a transport.
*
* <p>{@link Protocol#HTTP_1_0} is not supported in this set. Requests are initiated with {@code
* HTTP/1.1} only. If the server responds with {@code HTTP/1.0}, that will be exposed by {@link
* Response#protocol()}.
*
* @param protocols the protocols to use, in order of preference. The list must contain {@link
* Protocol#HTTP_1_1}. It must not contain null or {@link Protocol#HTTP_1_0}.
*/
public Builder protocols(List<Protocol> protocols) {
// Create a private copy of the list.
protocols = new ArrayList<>(protocols);
// Validate that the list has everything we require and nothing we forbid.
if (!protocols.contains(Protocol.HTTP_1_1)) {
throw new IllegalArgumentException("protocols doesn't contain http/1.1: " + protocols);
}
if (protocols.contains(Protocol.HTTP_1_0)) {
throw new IllegalArgumentException("protocols must not contain http/1.0: " + protocols);
}
if (protocols.contains(null)) {
throw new IllegalArgumentException("protocols must not contain null");
}
// Remove protocols that we no longer support.
protocols.remove(Protocol.SPDY_3);
// Assign as an unmodifiable list. This is effectively immutable.
this.protocols = Collections.unmodifiableList(protocols);
return this;
}
public Builder connectionSpecs(List<ConnectionSpec> connectionSpecs) {
this.connectionSpecs = Util.immutableList(connectionSpecs);
return this;
}
/**
* Returns a modifiable list of interceptors that observe the full span of each call: from
* before the connection is established (if any) until after the response source is selected
* (either the origin server, cache, or both).
*/
public List<Interceptor> interceptors() {
return interceptors;
}
public Builder addInterceptor(Interceptor interceptor) {
interceptors.add(interceptor);
return this;
}
/**
* Returns a modifiable list of interceptors that observe a single network request and response.
* These interceptors must call {@link Interceptor.Chain#proceed} exactly once: it is an error
* for a network interceptor to short-circuit or repeat a network request.
*/
public List<Interceptor> networkInterceptors() {
return networkInterceptors;
}
public Builder addNetworkInterceptor(Interceptor interceptor) {
networkInterceptors.add(interceptor);
return this;
}
// TODO(jwilson): make this public after the 3.8 release.
/*public*/ Builder eventListener(EventListener eventListener) {
if (eventListener == null) throw new NullPointerException("eventListener == null");
this.eventListenerFactory = EventListener.factory(eventListener);
return this;
}
// TODO(jwilson): make this public after the 3.8 release.
/*public*/ Builder eventListenerFactory(EventListener.Factory eventListenerFactory) {
if (eventListenerFactory == null) {
throw new NullPointerException("eventListenerFactory == null");
}
this.eventListenerFactory = eventListenerFactory;
return this;
}
//上面所有的代码都是为了这个最后的方法 构建
public OkHttpClient build() {
return new OkHttpClient(this);
}
}//内部Builder构建者类结束
}//game over
请高手在评论中帮忙解释下这个类里的方法功能,分享学习下,谢过先^_^