Bootstrap

Okhttp3 - 笔记

okhttp3 的优点
1 内部封装了连接池减少请求延迟
2 对http2 协议进行了封装
3 分发器
4 拦截器
5 相应缓存避免重复请求
6 自动重定向

okhttp3 使用流程

  OkHttpClient client = new OkHttpClient();

        //POST方式提交String
        MediaType mediaType = MediaType.parse("text/x-markdown; charset=utf-8");
        String requestBody = "I xxxxxx xxx";
        Request request = new Request.Builder()
                .url("http://xxx.xxx.xxx")
                .addHeader("","")
                .post(RequestBody.create(mediaType, requestBody))
                .build();

        //GET 请求
        Request request2 = new Request.Builder()
                .url("http://xxx.xxx.xxx")
                .addHeader("","")
                .get()//默认就是GET请求,可以不写
                .build();

        //POST提交文件
        MediaType mediaType2 = MediaType.parse("text/x-markdown; charset=utf-8");
        OkHttpClient okHttpClient = new OkHttpClient();
        File file = new File("test.md");
        Request request3 = new Request.Builder()
                .url("http://xxx.xxx.xxx")
                .post(RequestBody.create(mediaType, file))
                .build();

        //POST方式提交表单
        RequestBody requestBody4 = new FormBody.Builder()
                .add("search", "zxd")
                .build();
        Request request4 = new Request.Builder()
                .url("http://xxx.xxx.xxx")
                .post(requestBody4)
                .build();


        final Call call = client.newCall(request);

        try {
            //同步请求
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Response response = call.execute();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        } catch (Exception e) {
            e.printStackTrace();
        }

        // 异步请求
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                String result = response.body().toString();
            }
        });

okhttp 分发器

// 创建Call 时 通过newCall 创建一个RealCall 的实例
final Call call = client.newCall(request);
 
 @Override public Call newCall(Request request) {
    return RealCall.newRealCall(this, request, false /* for web socket */);
  }
// 异步请求 调用 RealCall  的 enqueue 方法
call.enqueue(new Callback() {
// 异步方法调用 OkHttpClient  的  dispatcher() Dispatcher类
// 也可以自定义 Dispatcher类 
@Override public void enqueue(Callback responseCallback) {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    eventListener.callStart(this);
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }
synchronized void enqueue(AsyncCall call) {
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      runningAsyncCalls.add(call);
      executorService().execute(call);
    } else {
      readyAsyncCalls.add(call);
    }
  }

异步请求时 包含两个队列 runningAsyncCalls 和 readyAsyncCalls
同步请求时 包含一个队列 runningSyncCalls

  /** Ready async calls in the order they'll be run. */
  private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>();

  /** Running asynchronous calls. Includes canceled calls that haven't finished yet. */
  private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();

  /** Running synchronous calls. Includes canceled calls that haven't finished yet. */
  private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();

okhttp3 分发时首先判断 runningAsyncCalls 中的数量是否大于 最大请求数 ,
maxRequests 默认值 64 可修改

 private int maxRequests = 64;
  public synchronized void setMaxRequests(int maxRequests) {
    if (maxRequests < 1) {
      throw new IllegalArgumentException("max < 1: " + maxRequests);
    }
    this.maxRequests = maxRequests;
    promoteCalls();
  }

runningCallsForHost(call) < maxRequestsPerHost) {判断 同host 的请求数不超过 5 个
maxRequestsPerHost 默认值 5 可修改

  private int maxRequestsPerHost = 5;
  public synchronized void setMaxRequestsPerHost(int maxRequestsPerHost) {
    if (maxRequestsPerHost < 1) {
      throw new IllegalArgumentException("max < 1: " + maxRequestsPerHost);
    }
    this.maxRequestsPerHost = maxRequestsPerHost;
    promoteCalls();
  }
  /** Returns the number of running calls that share a host with {@code call}. */
  private int runningCallsForHost(AsyncCall call) {
    int result = 0;
    for (AsyncCall c : runningAsyncCalls) {
      if (c.get().forWebSocket) continue;
      if (c.host().equals(call.host())) result++;
    }
    return result;
  }

1 当 runningAsyncCalls 队列数量大于 64
2 同类型服务器请求数量大于 5
readyAsyncCalls 队列添加数据

  synchronized void enqueue(AsyncCall call) {
    if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
      runningAsyncCalls.add(call);
      executorService().execute(call);
    } else {
      readyAsyncCalls.add(call);
    }
  }

executorService() // 获取线程池 
executorService().execute(call);  //线程池执行 call 就是执行线程的 run 方法

AsyncCall call

  final class AsyncCall extends NamedRunnable
ublic abstract class NamedRunnable implements Runnable {
@Override public final void run() {
    String oldName = Thread.currentThread().getName();
    Thread.currentThread().setName(name);
    try {
      execute();
    } finally {
      Thread.currentThread().setName(oldName);
    }
  }

  protected abstract void execute();

所以最后会执行 AsyncCall 的 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);
      }
    }
  }

发起 请求的返回 Response

  Response response = getResponseWithInterceptorChain();

无论成功与否 最后都会执行 finished 方法

finally {
        client.dispatcher().finished(this);
        thisAsyncCall
      }
  /** Used by {@code AsyncCall#run} to signal completion. */
  void finished(AsyncCall call) {
    finished(runningAsyncCalls, call, true);
  }

finished 方法中
1 calls.remove(call) 移除 runningAsyncCalls 中执行完成的 call
2 执行 promoteCalls(); 方法

 private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
    int runningCallsCount;
    Runnable idleCallback;
    synchronized (this) {
      if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
      if (promoteCalls) promoteCalls();
      runningCallsCount = runningCallsCount();
      idleCallback = this.idleCallback;
    }

    if (runningCallsCount == 0 && idleCallback != null) {
      idleCallback.run();
    }
  }

promoteCalls 方法中 ,先判断两个状态
1 runningAsyncCalls 运行队列的数量 是否大于 64
2 readyAsyncCalls 等待队列中是否为空
然后 迭代器迭代 readyAsyncCalls 等待队列
1 获取到等待的请求 ,在此判断 运行对列中 ,包含该服务器的请求的数量是否大于5
2 如果大于5 就 返回 不处理
3 小于5 等待队列删除该请求call
4 把该请求添加到 运行对列中 并执行
5 添加完之后继续判断 是否超过最大可执行数 64

private void promoteCalls() {
    if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
    if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.

    for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
      AsyncCall call = i.next();

      if (runningCallsForHost(call) < maxRequestsPerHost) {
        i.remove();
        runningAsyncCalls.add(call);
        executorService().execute(call);
      }

      if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
    }
  }

okhttp3 同步对列

阻塞执行

 @Override public Response execute() throws IOException {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;
    }
    captureCallStackTrace();
    eventListener.callStart(this);
    try {
      client.dispatcher().executed(this);
      Response result = getResponseWithInterceptorChain();
      if (result == null) throw new IOException("Canceled");
      return result;
    } catch (IOException e) {
      eventListener.callFailed(this, e);
      throw e;
    } finally {
      client.dispatcher().finished(this);
    }
  }

1 添加到同步对列中

  /** Used by {@code Call#execute} to signal it is in-flight. */
  synchronized void executed(RealCall call) {
    runningSyncCalls.add(call);
  }

2 进行请求

 Response result = getResponseWithInterceptorChain();

3 返回

 client.dispatcher().finished(this);
 thisRealCall 
  /** Used by {@code Call#execute} to signal completion. */
  void finished(RealCall call) {
    finished(runningSyncCalls, call, false);
  }

第三个参数传入 false

  void finished(RealCall call) {
    finished(runningSyncCalls, call, false);
  }

所以在 finished 中 不走 promoteCalls()方法 跳过readyAsyncCalls对列的操作

private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
    int runningCallsCount;
    Runnable idleCallback;
    synchronized (this) {
      if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
      if (promoteCalls) promoteCalls();
      runningCallsCount = runningCallsCount();
      idleCallback = this.idleCallback;
    }

    if (runningCallsCount == 0 && idleCallback != null) {
      idleCallback.run();
    }
  }

okhttp 的拦截器
拦截器入口

 Response result = getResponseWithInterceptorChain();
 Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List<Interceptor> 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 (!forWebSocket) {
      interceptors.addAll(client.networkInterceptors());
    }
    interceptors.add(new CallServerInterceptor(forWebSocket));

    Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
        originalRequest, this, eventListener, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());

    return chain.proceed(originalRequest);
  }

1 添加自定义拦截器

    interceptors.addAll(client.interceptors());

添加 retryAndFollowUpInterceptor拦截器 请求转发的内容

	 interceptors.add(retryAndFollowUpInterceptor);

添加 BridgeInterceptor拦截器 主要是处理 header头的内容

    interceptors.add(new BridgeInterceptor(client.cookieJar()));

添加 CacheInterceptor拦截器 主要是处理缓存

    interceptors.add(new CacheInterceptor(client.internalCache()));

添加 ConnectInterceptor拦截器 打开了与服务器的链接,正式开启了网络请求

    interceptors.add(new ConnectInterceptor(client.cookieJar()));

添加 自定义WebSocket 相关拦截器

  if (!forWebSocket) {
      interceptors.addAll(client.networkInterceptors());
    }

添加 CallServerInterceptor拦截器 向服务器发送请求,并最终返回Response对象供客户端使用。

    interceptors.add(new CallServerInterceptor(client.cookieJar()));

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;