读OkHttp3源码(一):OkHttpClient

1,简介:OkHttpClient是Call的的工厂,可用于发送HTTP请求并读取其响应。 大多数应用程序可以对所有HTTP请求使用一个OkHttpClient,这得益于共享的响应缓存线程池连接重用等等。

  • 要使用默认设置创建OkHttpClient,请使用默认构造函数。
  • 或者使用OkHttpClient.Builder创建自定义配置的实例。
  • 要在发出请求之前调整现有客户端,请使用newBuilder()。

2,构造方法:

public OkHttpClient() {
    this(new Builder());
}

默认构造方法调用另外一个私有构造方法,需要传入一个Builder对象:

private 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.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;
        } else {
            try {
                SSLContext sslContext = SSLContext.getInstance("TLS");
                sslContext.init(null, null, null);
                this.sslSocketFactory = sslContext.getSocketFactory();
            } catch (GeneralSecurityException e) {
                //系统没有TLS。就放弃。
                throw new AssertionError();
            }
        }
        if (sslSocketFactory != null && builder.trustRootIndex == 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.trustRootIndex = Platform.get().trustRootIndex(trustManager);
            this.certificatePinner = builder.certificatePinner.newBuilder()
                    .trustRootIndex(trustRootIndex)
                    .build();
        } else {
            this.trustRootIndex = builder.trustRootIndex;
            this.certificatePinner = builder.certificatePinner;
        }
        this.hostnameVerifier = builder.hostnameVerifier;
        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;
    }

通过builder对象默认的属性对OkHttpClient里的dispatcher(调度器)、proxy(代理)、protocols(支持协议)、connectionSpecs(连接策略)、interceptors(拦截器)、networkInterceptors(网络拦截器)、proxySelector(代理选择器)、cookieJar(cookie存储)、cache(缓存)、internalCache(okHttp自己使用的缓存,不对外)、socketFactory(套接字工厂)、sslSocketFactory(ssl套接字工厂)、trustRootIndex(可信赖根)、hostnameVerifier(主机名称校验器)、certificatePinner(固定证书)、proxyAuthenticator(代理服务器授权验证)

 

/**
 * 请求(calls)的的工厂类,可用于发送HTTP请求并读取其响应。
 * 大多数应用程序可以对所有HTTP请求使用一个OkHttpClient,这得益于共享的响应缓存、线程池、连接重用等等。
 * 要使用默认设置创建OkHttpClient,请使用默认构造函数。或者使用OkHttpClient.Builder创建自定义配置的实例。
 * 要在发出请求之前调整现有客户端,请使用newBuilder()。
 * 这个例子显示了一个超时30秒的调用:
 * 
 *     OkHttpClient client = ...
 *     OkHttpClient clientWith30sTimeout = client.newBuilder()
 *          .readTimeout(30, TimeUnit.SECONDS)
 *          .build();
 *    Response response = clientWith30sTimeout.newCall(request).execute();
 * 
*/ public class OkHttpClient implements Cloneable, Call.Factory { private static final List DEFAULT_PROTOCOLS = Util.immutableList( Protocol.HTTP_2, Protocol.SPDY_3, Protocol.HTTP_1_1); private static final List DEFAULT_CONNECTION_SPECS = Util.immutableList( ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_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 InternalCache internalCache(OkHttpClient client) { return client.internalCache(); } @Override public boolean connectionBecameIdle( ConnectionPool pool, RealConnection connection) { return pool.connectionBecameIdle(connection); } @Override public RealConnection get( ConnectionPool pool, Address address, StreamAllocation streamAllocation) { return pool.get(address, streamAllocation); } @Override public void put(ConnectionPool pool, RealConnection connection) { pool.put(connection); } @Override public RouteDatabase routeDatabase(ConnectionPool connectionPool) { return connectionPool.routeDatabase; } @Override public void callEnqueue(Call call, Callback responseCallback, boolean forWebSocket) { ((RealCall) call).enqueue(responseCallback, forWebSocket); } @Override public StreamAllocation callEngineGetStreamAllocation(Call call) { return ((RealCall) call).engine.streamAllocation; } @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); } }; } final Dispatcher dispatcher; final Proxy proxy; final List protocols; final List connectionSpecs; final List interceptors; final List networkInterceptors; final ProxySelector proxySelector; final CookieJar cookieJar; final Cache cache; final InternalCache internalCache; final SocketFactory socketFactory; final SSLSocketFactory sslSocketFactory; final TrustRootIndex trustRootIndex; 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; public OkHttpClient() { this(new Builder()); } private 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.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; } else { try { SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, null, null); this.sslSocketFactory = sslContext.getSocketFactory(); } catch (GeneralSecurityException e) { //系统没有TLS。就放弃。 throw new AssertionError(); } } if (sslSocketFactory != null && builder.trustRootIndex == 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.trustRootIndex = Platform.get().trustRootIndex(trustManager); this.certificatePinner = builder.certificatePinner.newBuilder() .trustRootIndex(trustRootIndex) .build(); } else { this.trustRootIndex = builder.trustRootIndex; this.certificatePinner = builder.certificatePinner; } this.hostnameVerifier = builder.hostnameVerifier; 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; } /** * 默认的连接超时(以毫秒为单位) */ public int connectTimeoutMillis() { return connectTimeout; } /** * 默认的读超时(以毫秒为单位) */ public int readTimeoutMillis() { return readTimeout; } /** * 默认的写超时(以毫秒为单位) */ public int writeTimeoutMillis() { return writeTimeout; } 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 protocols() { return protocols; } public List connectionSpecs() { return connectionSpecs; } /** * 返回一个不可变的拦截器列表,该列表观察每个请求(call)的整个持续时间: * 从建立连接之前(如果有的话)到选择响应源之后(源服务器、缓存或者两者都选择)。 */ public List interceptors() { return interceptors; } /** * 这些拦截器必须精确地调用Interceptor.Chain一次,因为网络拦截器短路或重复网络请求是会报错的。 */ public List networkInterceptors() { return networkInterceptors; } /** * 准备将来某个时候要执行的request。 */ @Override public Call newCall(Request request) { return new RealCall(this, request); } public Builder newBuilder() { return new Builder(this); } public static final class Builder { Dispatcher dispatcher; Proxy proxy; List protocols; List connectionSpecs; final List interceptors = new ArrayList<>(); final List networkInterceptors = new ArrayList<>(); ProxySelector proxySelector; CookieJar cookieJar; Cache cache; InternalCache internalCache; SocketFactory socketFactory; SSLSocketFactory sslSocketFactory; TrustRootIndex trustRootIndex; HostnameVerifier hostnameVerifier; CertificatePinner certificatePinner; Authenticator proxyAuthenticator; Authenticator authenticator; ConnectionPool connectionPool; Dns dns; boolean followSslRedirects; boolean followRedirects; boolean retryOnConnectionFailure; int connectTimeout; int readTimeout; int writeTimeout; public Builder() { dispatcher = new Dispatcher(); protocols = DEFAULT_PROTOCOLS; connectionSpecs = DEFAULT_CONNECTION_SPECS; proxySelector = ProxySelector.getDefault(); cookieJar = CookieJar.NO_COOKIES; socketFactory = SocketFactory.getDefault(); 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; } 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.proxySelector = okHttpClient.proxySelector; this.cookieJar = okHttpClient.cookieJar; this.internalCache = okHttpClient.internalCache; this.cache = okHttpClient.cache; this.socketFactory = okHttpClient.socketFactory; this.sslSocketFactory = okHttpClient.sslSocketFactory; this.trustRootIndex = okHttpClient.trustRootIndex; 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; } /** * 为新连接设置默认连接超时。值为0表示没有超时,否则值必须在1和Integer.MAX_VALUE之间所对应转换的毫秒。 */ public Builder connectTimeout(long timeout, TimeUnit unit) { if (timeout < 0) throw new IllegalArgumentException("timeout < 0"); if (unit == null) throw new IllegalArgumentException("unit == null"); long millis = unit.toMillis(timeout); if (millis > Integer.MAX_VALUE) throw new IllegalArgumentException("Timeout too large."); if (millis == 0 && timeout > 0) throw new IllegalArgumentException("Timeout too small."); connectTimeout = (int) millis; return this; } /** * 为新连接设置默认读超时。值为0表示没有超时,否则值必须在1和Integer.MAX_VALUE之间所对应转换的毫秒。 */ public Builder readTimeout(long timeout, TimeUnit unit) { if (timeout < 0) throw new IllegalArgumentException("timeout < 0"); if (unit == null) throw new IllegalArgumentException("unit == null"); long millis = unit.toMillis(timeout); if (millis > Integer.MAX_VALUE) throw new IllegalArgumentException("Timeout too large."); if (millis == 0 && timeout > 0) throw new IllegalArgumentException("Timeout too small."); readTimeout = (int) millis; return this; } /** * 为新连接设置默认写超时。值为0表示没有超时,否则值必须在1和Integer.MAX_VALUE之间所对应转换的毫秒。 */ public Builder writeTimeout(long timeout, TimeUnit unit) { if (timeout < 0) throw new IllegalArgumentException("timeout < 0"); if (unit == null) throw new IllegalArgumentException("unit == null"); long millis = unit.toMillis(timeout); if (millis > Integer.MAX_VALUE) throw new IllegalArgumentException("Timeout too large."); if (millis == 0 && timeout > 0) throw new IllegalArgumentException("Timeout too small."); writeTimeout = (int) millis; return this; } /** * 设置此client创建的连接将使用的HTTP代理。 * 这优先于proxySelector,proxySelector只在这个代理为null(默认为null)时才被使用。 * 要完全禁用代理使用,请调用setProxy(Proxy.no_proxy)。 */ public Builder proxy(Proxy proxy) { this.proxy = proxy; return this; } /** * 如果没有显式指定代理{@link #proxy 代理} ,则这时设置的代理选择策略将被使用。 * 代理选择器可以返回多个代理;在这种情况下,他们将依次进行尝试,直到建立成功的连接。 * 如果未设置,将使用系统范围内的{@link ProxySelector#getDefault() 默认代理选择器}。 */ public Builder proxySelector(ProxySelector proxySelector) { this.proxySelector = proxySelector; return this; } /** * 设置可以接受来自传入HTTP响应的cookie的处理程序,并向发出的HTTP请求提供cookie。 * 如果未设置,则不接受或不提供cookie{@linkplain CookieJar#NO_COOKIES (no cookies)} */ public Builder cookieJar(CookieJar cookieJar) { if (cookieJar == null) { throw new NullPointerException("cookieJar == null"); } this.cookieJar = cookieJar; return this; } /** * 设置response缓存,用于读写缓存的response。 */ void setInternalCache(InternalCache internalCache) { this.internalCache = internalCache; this.cache = null; } public Builder cache(Cache cache) { this.cache = cache; this.internalCache = null; return this; } /** * 设置用于查找主机名的IP地址的DNS服务。 * 如果未设置,将使用{@link Dns#SYSTEM 系统范围内的默认DNS}。 */ public Builder dns(Dns dns) { if (dns == null) { throw new NullPointerException("dns == null"); } this.dns = dns; return this; } /** * 设置用于创建连接的套接字工厂。 * OkHttp仅使用无参数的{@link SocketFactory#createSocket() createSocket()}方法创建未连接的套接字。重写这个方法,例如。,允许套接字绑定到特定的本地地址。 * 如果未设置,将使用{@link SocketFactory#getDefault() 系统范围内的默认套接字工厂}。 */ public Builder socketFactory(SocketFactory socketFactory) { if (socketFactory == null) { throw new NullPointerException("socketFactory == null"); } this.socketFactory = socketFactory; return this; } /** * 设置用于保护HTTPS连接的套接字工厂。 * 如果未设置,将使用惰性创建的SSL套接字工厂。 */ public Builder sslSocketFactory(SSLSocketFactory sslSocketFactory) { if (sslSocketFactory == null) { throw new NullPointerException("sslSocketFactory == null"); } this.sslSocketFactory = sslSocketFactory; this.trustRootIndex = null; return this; } /** * 设置用于确认response证书应用于HTTPS连接所请求的主机名的验证程序。 * 如果未设置,将使用默认主机名验证器 */ public Builder hostnameVerifier(HostnameVerifier hostnameVerifier) { if (hostnameVerifier == null) { throw new NullPointerException("hostnameVerifier == null"); } this.hostnameVerifier = hostnameVerifier; return this; } /** * 设置约束哪些证书受信任的固定证书。 * 默认情况下,HTTPS连接仅依赖SSL套接字工厂来建立信任。 * 固定证书可以避免信任证书颁发机构。 */ public Builder certificatePinner(CertificatePinner certificatePinner) { if (certificatePinner == null) { throw new NullPointerException("certificatePinner == null"); } this.certificatePinner = certificatePinner; return this; } /** * 设置用于响应来自源服务器的挑战的验证器。使用{@link #proxyAuthenticator} 设置代理服务器的authenticator。 * 如果未设置,将尝试 {@linkplain Authenticator#NONE 无身份验证}。 */ public Builder authenticator(Authenticator authenticator) { if (authenticator == null) { throw new NullPointerException("authenticator == null"); } this.authenticator = authenticator; return this; } /** * 设置用于响应来自代理服务器的挑战的验证器。使用{@link #authenticator}设置原始服务器的authenticator。 * 如果未设置,将尝试{@linkplain Authenticator#NONE 无身份验证}。 */ public Builder proxyAuthenticator(Authenticator proxyAuthenticator) { if (proxyAuthenticator == null) { throw new NullPointerException("proxyAuthenticator == null"); } this.proxyAuthenticator = proxyAuthenticator; return this; } /** * 设置连接池,用于循环使用HTTP和HTTPS连接。 * 如果没有设置,将会使用一个新的连接池。 */ public Builder connectionPool(ConnectionPool connectionPool) { if (connectionPool == null) { throw new NullPointerException("connectionPool == null"); } this.connectionPool = connectionPool; return this; } /** * 配置此client以遵循从HTTPS到HTTP以及从HTTP到HTTPS的重定向。 * 如果未设置,则遵循协议重定向。这与内置{@code HttpURLConnection}的默认值不同。 */ public Builder followSslRedirects(boolean followProtocolRedirects) { this.followSslRedirects = followProtocolRedirects; return this; } /** * 配置此client以遵循重定向。如果未设置,则遵循重定向。 */ public Builder followRedirects(boolean followRedirects) { this.followRedirects = followRedirects; return this; } /** * 配置此client在遇到连接问题时重试或不重试。默认情况下,该客户端会从以下问题中恢复过来: *
    *
  • 遥不可及的IP地址。如果URL的主机有多个IP地址,未能到达任何单个IP地址不会导致整个请求失败。这可以增加多宿主服务的可用性。
  • *
  • 陈旧的连接池。{@link ConnectionPool}重用套接字以减少请求延迟,但这些连接偶尔会超时。
  • *
  • 遥不可及的代理服务器。{@link ProxySelector}可用于依次尝试多个代理服务器,最终返回到直接连接。
  • *
* 将此设置为false以避免重试请求,这样做是具有破坏性的。在这种情况下,调用应用程序应该自行恢复连接故障。 */ public Builder retryOnConnectionFailure(boolean retryOnConnectionFailure) { this.retryOnConnectionFailure = retryOnConnectionFailure; return this; } /** * 设置用于设置策略和执行异步请求的调度程序。不能为空。 */ public Builder dispatcher(Dispatcher dispatcher) { if (dispatcher == null) { throw new IllegalArgumentException("dispatcher == null"); } this.dispatcher = dispatcher; return this; } /** * 配置此client与远程服务器通信使用的协议。 * 默认情况下,这个client会选择最有效的传输方式,回归到更普遍的协议。 * 应用程序应该只调用此方法来避免特定的兼容性问题,比如启用SPDY时web服务器出现错误的行为。 * *

以下是目前支持的协议: * *

* *

This is an evolving set. Future releases include support for transitional * protocols. The http/1.1 transport will never be dropped. * *

If multiple protocols are specified, ALPN will be used to * negotiate a transport. * *

{@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 protocols) { protocols = Util.immutableList(protocols); 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"); } this.protocols = Util.immutableList(protocols); return this; } public Builder connectionSpecs(List connectionSpecs) { this.connectionSpecs = Util.immutableList(connectionSpecs); return this; } /** * 返回一个可修改的拦截器列表,该列表可以观察每个call的整个持续时间: * 从建立连接之前(如果有的话)到选择响应源之后(源服务器、缓存或者两者都选择)。 */ public List interceptors() { return interceptors; } public Builder addInterceptor(Interceptor interceptor) { interceptors.add(interceptor); return this; } /** * 返回观察单个网络请求和响应的可修改的拦截器列表。 * 这些拦截器必须调用{@link Interceptor.Chain#proceed}Interceptor.Chain一次:网络拦截器短路或重复网络请求会报错。 */ public List networkInterceptors() { return networkInterceptors; } public Builder addNetworkInterceptor(Interceptor interceptor) { networkInterceptors.add(interceptor); return this; } public OkHttpClient build() { return new OkHttpClient(this); } } }

 

 

你可能感兴趣的:(OkHttp)