这就是一个标准的构建者模式,将http请求的一些配置封装到client对象中。
2. 构建Request请求对象
public final class Request { final HttpUrl url; final String method; final Headers headers; final @Nullable RequestBody body; final Map<Class<?>, Object> tags; public static class Builder { @Nullable HttpUrl url; String method; Headers.Builder headers; @Nullable RequestBody body; public Builder() { this.method = “GET”; this.headers = new Headers.Builder(); } Builder(Request request) { this.url = request.url; this.method = request.method; this.body = request.body; this.tags = request.tags.isEmpty() ? Collections.emptyMap() : new LinkedHashMap<>(request.tags); this.headers = request.headers.newBuilder(); } } }
这也是一个建造者模式把请求的url
、method
、header
全部封装到Request
对象中。
3. 创建Call对象
先来看看Call,这是一个接口,定义了一些request()
、enqueue(Callback responseCallback)
、execute()
等方法,其实现类是RealCall,先搁置一边。回过头来看client.newCall(request)
跟进代码,查看newCall(Request request)
方法。
OkHttpClient
类:
@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) { // Safely publish the Call instance to the EventListener. RealCall call = new RealCall(client, originalRequest, forWebSocket); call.eventListener = client.eventListenerFactory().create(call); return call; }
果然,这里就只是跟进传进来的Request和当前的client对象创建了一个RealCall对象,也就是说使用方法中的第三步(Call call = client.newCall(request)
)执行完成后,得到了一个ReallCall对象,接下来到了第四步。
4. 发起请求
先看execute = call.execute()
请求
a).同步请求execute() @Override public Response execute() throws IOException { synchronized (this) { //一个请求只能执行一次 if (executed) throw new IllegalStateException(“Already Executed”); executed = true; } captureCallStackTrace(); timeout.enter(); //http请求调用的生命周期 eventListener.callStart(this); try { client.dispatcher().executed(this);//注释1 Response result = getResponseWithInterceptorChain();//注释2 if (result == null) throw new IOException(“Canceled”); return result; } catch (IOException e) { e = timeoutExit(e); eventListener.callFailed(this, e); throw e; } finally { client.dispatcher().finished(this); } } 关键代码为标出来的注释1和注释2两处,先看注释1,看下client.dispatcher()返回的Dispatcher对象: /** * Policy on when async requests are executed. * * Each dispatcher uses an {@link ExecutorService} to run calls internally. If you supply your * own executor, it should be able to run {@linkplain #getMaxRequests the configured maximum} number * of calls concurrently. /public final class Dispatcher { //最大请求数 private int maxRequests = 64; //每一个主机的最大请求数 private int maxRequestsPerHost = 5; private @Nullable Runnable idleCallback; /* Executes calls. Created lazily. / //线程池 private @Nullable ExecutorService executorService; /* Ready async calls in the order they’ll be run. / //准备执行的异步请求队列 private final Deque readyAsyncCalls = new ArrayDeque<>(); /* Running asynchronous calls. Includes canceled calls that haven’t finished yet. / //正在执行的异步请求队列 private final Deque runningAsyncCalls = new ArrayDeque<>(); /* Running synchronous calls. Includes canceled calls that haven’t finished yet. / //正在执行的同步请求队列 private final Deque runningSyncCalls = new ArrayDeque<>(); public Dispatcher(ExecutorService executorService) { this.executorService = executorService; } void enqueue(AsyncCall call) { synchronized (this) { readyAsyncCalls.add(call); // Mutate the AsyncCall so that it shares the AtomicInteger of an existing running call to // the same host. if (!call.get().forWebSocket) { AsyncCall existingCall = findExistingCallWithHost(call.host()); if (existingCall != null) call.reuseCallsPerHostFrom(existingCall); } } promoteAndExecute(); } /* Used by {@code Call#execute} to signal it is in-flight. */ synchronized void executed(RealCall call) { runningSyncCalls.add(call); } //…代码略… } 这是一个调度器,内部维护着最大请求数,每个主机最大请求数等参数,最重要的是维护着三个队列,分别是“将要执行的异步请求队列”、“正在执行的异步请求队列”和“正在执行的同步执行队列”。之前的代码段中注释1处调用dispatcher.executed(this)方法,我们看到这个方法只是把当前的realCall实例加入到了请求队列中。接下来看注释2处的代码Response result = getResponseWithInterceptorChain(),看下这个方法: 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 (!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); } 在这个方法中,将用户自定义的一些拦截器和默认的拦截器封装到一个list中,然后创建RealInterceptorChain对象并执行proceed(originalRequest)方法,接下来将是重点。看一下这个方法 public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec, RealConnection connection) throws IOException { //…省去异常处理… // Call the next interceptor in the chain. RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec, connection, index + 1, request, call,eventListener, connectTimeout, readTimeout,writeTimeout); Interceptor interceptor = interceptors.get(index); Response response = interceptor.intercept(next); //…省去异常处理… return response; } 关键代码只有三行,这里会遍历调用拦截器列表中的拦截器,并调用每一个拦截器的intercept(RealInterceptorChain chain)方法,先看这里的第一个拦截器RetryAndFollowUpInterceptor的intercept(Chain chain)方法 @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); RealInterceptorChain realChain = (RealInterceptorChain) chain; //…省略部分代码… int followUpCount = 0; Response priorResponse = null; while (true) { //…省略异常处理代码… Response response; boolean releaseConnection = true; try { //注释3 response = realChain.proceed(request, streamAllocation, null, null); releaseConnection = false; } catch (RouteException e) { // The attempt to connect via a route failed. The request will not have been sent. if (!recover(e.getLastConnectException(), streamAllocation, false, request)) { throw e.getFirstConnectException(); } releaseConnection = false; continue; } catch (IOException e) { // An attempt to communicate with a server failed. The request may have been sent. boolean requestSendStarted = !(e instanceof ConnectionShutdownException); if (!recover(e, streamAllocation, requestSendStarted, request)) throw e; releaseConnection = false; continue; } finally { // We’re throwing an unchecked exception. Release any resources. if (releaseConnection) { streamAllocation.streamFailed(null); streamAllocation.release(true); } } // Attach the prior response if it exists. Such responses never have a body. if (priorResponse != null) {