OkhttpClient学习

OkHttpClient 学习和使用

先通过一个非常简单的例子来看怎样使用OKHttpClient发送一个请求,然后根据这个简单例子来详细的分析每个步骤。

        OkHttpClient client = new OkHttpClient().newBuilder().build();
        Request request = new Request.Builder().url("http://www.baidu.com").build();
        Response response = client.newCall(request).execute();
        ResponseBody responseBody = response.body();

这是一个通过OkHttpClient发送一个简单的get请求百度首页的过程。

  1. 创建一个OkHttpClient实例
  2. 创建一个Request实例
  3. 使用 OkHttpClient 创建一个Call并执行 execute()方法,得到一个Response对象。
  4. Response 进行相关操作。

以上就是整个简单HTTP请求的发送和接收过程。

OkHttpClient实现了CloneableCall.Factory接口,Cloneable接口表示okhttpclient支持Object的clone方法。Call.Factory接口是通过Request创建一个Call。同时也要实现Call.FactorynewCall方法。
OkHttpClient通过内部的Builder类来创建。生成器模式,new OkHttpClient(){ this(new Builder())} 或者new OkHttpClient.Builder().build().创建OkHttpClient的方式比较多,这样都是使用默认的OkHttpClient的配置。
相关可以配置的和Client相关的还有

  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);
  //使用https的版本和密码套件
  final Dispatcher dispatcher;//调度,异步请求
  final Proxy proxy;//代理 java.net
  final List protocols;
  final List connectionSpecs;
  final List interceptors;//拦截器
  final List networkInterceptors;//网络拦截器
  final ProxySelector proxySelector;//代理选择器
  final CookieJar cookieJar;//http cookies 管理方案和 持久化
  final Cache cache;//缓存
  final InternalCache internalCache;//内部缓存
  final SocketFactory socketFactory;//socket 工厂 java.net
  final SSLSocketFactory sslSocketFactory; //SSLSocket 工厂 java.net.ssl 
  final CertificateChainCleaner certificateChainCleaner;//证书方案
  final HostnameVerifier hostnameVerifier;//hostName 校验 OkHostnameVerifier
  final CertificatePinner certificatePinner;//固定的证书
  final Authenticator proxyAuthenticator;//代理的身份认证
  final Authenticator authenticator;// web的身份认证
  final ConnectionPool connectionPool;//连接池
  final Dns dns;//DNS
  final boolean followSslRedirects;//是否 执行 ssl redirect
  final boolean followRedirects;//是否执行 redirect
  final boolean retryOnConnectionFailure; //连接失败后是否重试
  final int connectTimeout;//连接超时时间
  final int readTimeout;// 读取超时
  final int writeTimeout;// 写入超时

Request和Client一样也是使用生成器模式完成的。
Request中包含了

  private final HttpUrl url;
  private final String method;
  private final Headers headers;
  private final RequestBody body;
  private final Object tag;

  private volatile CacheControl cacheControl; // Lazily initialized.

Request 中包含的内容都是比较清晰的,一个是HttpUrl对象。主要内容就是请求地址,实例化的时候可以指定,协议,端口等。method就是指请求方法,Headers是请求头的封装。RequestBody就是请求主体。

HttpUrl 的使用

    HttpUrl url = new HttpUrl.Builder()
        .scheme("https")
        .host("www.baidu.com")
        .addPathSegment("s")
        .addQueryParameter("wd", "dota2")
        .build();
    System.out.println(url);
 //  https://www.baidu.com/s?wd=dota2

得到了一个HttpUrl。还有很多其他的方法:
queryParameterName()queryParameterValue 获取get请求参数 等。

RequestBody是一个抽象类。还有两个子类FormBodyMultipartBody。主要差别在于MediaType.
回到例子中的Request对象,使用了默认的Request.Builder()来构建。默认的是get方法,默认的Header.Builder。tag默认是自身。

OkHttpClient 实现了Call.Factory接口,创建一个Call

public Call newCall(Request request) {
    return new RealCall(this, request);
  }

实际上接下来的工作都是由RealCall在完成的。
根据client和request创建一个RealCall实例,client被final修饰。默认会加上RetryAndFollowUpInterceptor参数。

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

然后就是execute()

  @Override public Response execute() throws IOException {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    try {
      client.dispatcher().executed(this);
      Response result = getResponseWithInterceptorChain();
      if (result == null) throw new IOException("Canceled");
      return result;
    } finally {
      client.dispatcher().finished(this);
    }
  }
  1. 检查这个Call是否被执行过
  2. 利用client.dispatcher.execute(this)来完成实际的请求过程。Dispatcher在client文档中的表示的是异步请求的调度。实际上同步请求也是通过他们来调度完成的
  3. Reqsponse是通过getResponseWithInterceptorChain()方法获得的。从方法名可知,会通过一系列的拦截器。
  4. 最后通知dispatcher执行完成。

具体的Dispatcher稍后看,先关注发送请求解析返回结果的getResponseWithInterceptorChain()

  private Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List interceptors = new ArrayList<>();
    interceptors.addAll(client.interceptors());
    interceptors.add(retryAndFollowUpInterceptor);
    interceptors.add(new BridgeInterceptor(client.cookieJar()));
    interceptors.add(new CacheInterceptor(client.internalCache()));
    interceptors.add(new ConnectInterceptor(client));
    if (!retryAndFollowUpInterceptor.isForWebSocket()) {
      interceptors.addAll(client.networkInterceptors());
    }
    interceptors.add(new CallServerInterceptor(
        retryAndFollowUpInterceptor.isForWebSocket()));

    Interceptor.Chain chain = new RealInterceptorChain(
        interceptors, null, null, null, 0, originalRequest);
    return chain.proceed(originalRequest);
  }

这个方法把网络请求,重试,缓存,压缩等操作都统一成一个个Interceptor。形成一个Interceptor.Chain,最后完成一次请求的过程。

通过getResponseWithInterceptorChain()可以看出Interceptor.Chain的组成部分:

  1. client.interceptors 构造client的时候设置的Interceptors
  2. retryAndFollowUpInterceptor负责失败重试和重定向。this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client);在构造RealCall时创建。
  3. 桥接,将请求转换成发送到服务器的请求、通过网络响应构造一个服务器的返回响应d的BridgeInterceptor
  4. 读取缓存返回,更新缓存的CacheInterceptor
  5. 和服务器创建连接的ConnectInterceptor
  6. CallServerInterceptor makes a network call to the server 最后一个Interceptor.
    然后创建一个Interceptor.Chain 实例,执行proceed方法。得到Response.

你可能感兴趣的:(OkhttpClient学习)