学习笔记

okhttp 源码分析
Publish: 2018/7/23   

根据okhttp使用,分析每一步相关源码

OkHttpClient.Builder builder = new OkHttpClient.Builder();
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(Constants.ISDEBUG? HttpLoggingInterceptor.Level.BODY : HttpLoggingInterceptor.Level.NONE);
OkHttpClient client = builder
    .addNetworkInterceptor(new DesInterceptor())
    .addInterceptor(logging)
    .build();

Builder()

默认配置,可根据对应参数的方法自定义配置

public Builder() {
      dispatcher = new Dispatcher(); //执行异步请求的策略,内部由1个ExecutorService调用
      protocols = DEFAULT_PROTOCOLS; //协议Protocol.HTTP_2和Protocol.HTTP_1_1

      //连接方式ConnectionSpec.MODERN_TLS(HTTPS), ConnectionSpec.CLEARTEXT(HTTP)      
      connectionSpecs = DEFAULT_CONNECTION_SPECS; 
      /*指标事件的监听器。扩展此类以监控应用程序HTTP调用的数量,大小和持续时间
        默认不处理
       */
      eventListenerFactory = EventListener.factory(EventListener.NONE);

      proxySelector = ProxySelector.getDefault(); //处理代理服务器,如果有
      cookieJar = CookieJar.NO_COOKIES; //处理Cookie 默认不处理
      socketFactory = SocketFactory.getDefault(); //创建socket
      hostnameVerifier = OkHostnameVerifier.INSTANCE; //安全证书验证
      certificatePinner = CertificatePinner.DEFAULT; //约束哪些证书是可信的
      proxyAuthenticator = Authenticator.NONE; //处理请求头 Proxy-Authorization 默认不处理
      authenticator = Authenticator.NONE; //处理请求头 Authorization  默认不处理

      /*为单个用户创建一个恰当参数的连接池,参数随版本变化。
        目前,该池最多可容纳5个闲置连接,闲置5分钟后将被驱逐。
        public ConnectionPool() {this(5, 5, TimeUnit.MINUTES);}
       */
      connectionPool = new ConnectionPool();

      /*使用InetAddress.getAllByName来请求底层操作系统查找IP地址的DNS。 
        大多数自定义的Dns实现应该委托给这个实例
       */
      dns = Dns.SYSTEM;

      followSslRedirects = true; //允许从HTTPS到HTTP以及从HTTP到HTTPS的重定向。
      followRedirects = true; //允许重定向

      /*配置此客户端在遇到连接问题时重试或不重试。 
        默认情况下,此客户端将从以下问题中静默恢复:
        * 无法访问的IP地址。 一个host对应多个IP。
        * 陈旧的连接池。ConnectionPool重用套接字来减少请求延迟,但这些连接偶尔会超时。 
        * 无法访问的代理服务器。ProxySelector可用于尝试按顺序多个代理服务器,最终回落到直接连接。
       */
      retryOnConnectionFailure = true;
      connectTimeout = 10_000; //默认连接超时(以毫秒为单位)。
      readTimeout = 10_000; //默认读取超时(以毫秒为单位)。
      writeTimeout = 10_000; //默认写入超时(以毫秒为单位)。
      pingInterval = 0; //Web套接字ping时间间隔(以毫秒为单位)。
    }

addNetworkInterceptor(new DesInterceptor())

返回观察单个网络请求和响应的拦截器的可修改列表。 这些拦截器必须调用Interceptor.Chain.proceed(okhttp3.Request)正好一次:它是一种用于在网络拦截到短路的错误或重复的网络请求。

当调用Response response = chain.proceed(request); 后,可使用下面方式重新返回Response

ResponseBody body = ResponseBody.create(mediaType, json);
return response.newBuilder().body(body).build();

addInterceptor(logging)

返回一个可修改的拦截器列表,用于观察每个调用的完整跨度:从连接建立之前(如果有)到选择响应源(源服务器,缓存或两者)之后。

build()

OkHttpClient(Builder builder) 将Builder中的参数对应的赋值给OkHttpClient

//通过isTLS判断是否是HTTPS连接
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);
}
如果使用HTTPS的话,可以通过Builder#sslSocketFactory( SSLSocketFactory sslSocketFactory, X509TrustManager trustManager)添加自定义的证书 ## 访问网络
String run(String url) throws IOException {
  Request request = new Request.Builder()
      .url(url)
      .build();

  Response response = client.newCall(request).execute();
  return response.body().string();
}

创建Request

Request(Builder builder) {
    this.url = builder.url; //访问地址
    this.method = builder.method; //请求方式 GET POST HEAD DELETE PUT PATCH
    this.headers = builder.headers.build(); //请求头 Headers
    this.body = builder.body; //请求体 RequestBody
    this.tag = builder.tag != null ? builder.tag : this;//标签,可以用来取消请求
  }

client.newCall(request)

准备将来要执行的请求。

@Override public Call newCall(Request request) {
    return RealCall.newRealCall(this, request, false /* for web socket */);
  }
->RealCall->static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    // 安全地将Call实例发布到EventListener。
    RealCall call = new RealCall(client, originalRequest, forWebSocket);
    call.eventListener = client.eventListenerFactory().create(call);
    return call;
  }

RealCall

private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    this.client = client;
    this.originalRequest = originalRequest;
    this.forWebSocket = forWebSocket;
    this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);
  }

/*这个拦截器从故障中恢复并在必要时遵循重定向。 
如果调用被取消,它可能会抛出IOException,因为底层是调用的socket.close
*/
->RetryAndFollowUpInterceptor
->public RetryAndFollowUpInterceptor(OkHttpClient client, boolean forWebSocket) {
    this.client = client;
    this.forWebSocket = forWebSocket;
  }

RealCall#execute()和enqueue()

同一个RealCall只能同时请求一次,不管是execute还是enqueue

executorService().execute(call);

//默认是一个数量无限制的线程池
->public synchronized ExecutorService executorService() {
    if (executorService == null) {
      executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
          new SynchronousQueue(), Util.threadFactory("OkHttp Dispatcher", false));
    }
    return executorService;
  }

AsyncCall

-> AsyncCall extends NamedRunnable

-> NamedRunnable implements Runnable#run()->execute()

//访问网络部分和同步请求一样,加了异步回调方法
@Override protected void execute() {
      boolean signalledCallback = false;
      try {
        Response response = getResponseWithInterceptorChain();
        if (retryAndFollowUpInterceptor.isCanceled()) {
          signalledCallback = true;
          responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
        } else {
          signalledCallback = true;
          responseCallback.onResponse(RealCall.this, response);
        }
      } catch (IOException e) {
        if (signalledCallback) {
          // Do not signal the callback twice!
          Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
        } else {
          eventListener.callFailed(RealCall.this, e);
          responseCallback.onFailure(RealCall.this, e);
        }
      } finally {
        client.dispatcher().finished(this);
      }
    }
  }


← RxJava2 源码分析 Java并发编程实战-7结构化并发应用程序_取消与关闭 →

Powered by Hexo, Theme designs by @hpcslag.
Style-Framework Tocas-UI designs by @yamioldmel