获取Okhttp中全部请求头(二)

截图再上传实在麻烦,就简单把代码复制过来....

其实我什么也没说,我只是代码的搬运工.....

第一篇的时候描述了下怎么获取所有请求头,这篇简单介绍下okhttp添加系统请求header的实现过程,首先看下面代码:

    private final OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder()
                .url("http://www.2cto.com/kf/201604/497726.html")
                .build();

        Response response = client.newCall(request).execute();
        if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

这段代码可以发起一个网络请求(注意放在子线程中执行)。

然后进入OkHttpClient.newCall(Request request)方法查看,代码如下:


    OkHttpClient.java

    @Override

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

    这里我们会看到newCall(Request request) 传入了一个Request请求,并返回了一个实例化的RealCall对象,

   继续进入RealCall类进行查看会发现RealCall类实现了Call接口。

   继续看最上面执行请求的代码,在返回RealCall的实例后进行了execute()方法的调用。继续进入RealCall类查看execute()方法,代码如下:

RealCall.java

@Override

public Response execute() throws IOException {
        synchronized(this) {
            if(this.executed) {
                throw new IllegalStateException("Already Executed");
            }


            this.executed = true;
        }


        Response var2;
        try {
            this.client.dispatcher().executed(this);
            Response result = this.getResponseWithInterceptorChain();
            if(result == null) {
                throw new IOException("Canceled");
            }


            var2 = result;
        } finally {
            this.client.dispatcher().finished(this);
        }


        return var2;
    }

注意标红的代码,继续进行查看getResponseWithInterceptorChain()方法:

RealCall.java

    private Response getResponseWithInterceptorChain() throws IOException {
        ArrayList interceptors = new ArrayList();
        interceptors.addAll(this.client.interceptors());
        interceptors.add(this.retryAndFollowUpInterceptor);
        interceptors.add(new BridgeInterceptor(this.client.cookieJar()));
        interceptors.add(new CacheInterceptor(this.client.internalCache()));
        interceptors.add(new ConnectInterceptor(this.client));
        if(!this.retryAndFollowUpInterceptor.isForWebSocket()) {
            interceptors.addAll(this.client.networkInterceptors());
        }


        interceptors.add(new CallServerInterceptor(this.retryAndFollowUpInterceptor.isForWebSocket()));
        RealInterceptorChain chain = new RealInterceptorChain(interceptors, (StreamAllocation)null, (HttpStream)null, (Connection)null, 0, this.originalRequest);
        return chain.proceed(this.originalRequest);
    }

   上面的代码可以知道这里添加了一堆拦截器,OkHttp里面的拦截器是一个强大的工具,可以做到对网络请求和响应的随意修改,

   下面继续查看标红的代码BridgeInterceptor类:

BridgeInterceptor.java

@Override

 public Response intercept(Chain chain) throws IOException {
        Request userRequest = chain.request();
        Builder requestBuilder = userRequest.newBuilder();
        RequestBody body = userRequest.body();
        if(body != null) {
            MediaType transparentGzip = body.contentType();
            if(transparentGzip != null) {
                requestBuilder.header("Content-Type", transparentGzip.toString());
            }


            long cookies = body.contentLength();
            if(cookies != -1L) {
                requestBuilder.header("Content-Length", Long.toString(cookies));
                requestBuilder.removeHeader("Transfer-Encoding");
            } else {
                requestBuilder.header("Transfer-Encoding", "chunked");
                requestBuilder.removeHeader("Content-Length");
            }
        }


        if(userRequest.header("Host") == null) {
            requestBuilder.header("Host", Util.hostHeader(userRequest.url(), false));
        }


        if(userRequest.header("Connection") == null) {
            requestBuilder.header("Connection", "Keep-Alive");
        }


        boolean transparentGzip1 = false;
        if(userRequest.header("Accept-Encoding") == null) {
            transparentGzip1 = true;
            requestBuilder.header("Accept-Encoding", "gzip");
        }


        List cookies1 = this.cookieJar.loadForRequest(userRequest.url());
        if(!cookies1.isEmpty()) {
            requestBuilder.header("Cookie", this.cookieHeader(cookies1));
        }


        if(userRequest.header("User-Agent") == null) {
            requestBuilder.header("User-Agent", Version.userAgent());
        }


        Response networkResponse = chain.proceed(requestBuilder.build());
        HttpHeaders.receiveHeaders(this.cookieJar, userRequest.url(), networkResponse.headers());
        okhttp3.Response.Builder responseBuilder = networkResponse.newBuilder().request(userRequest);
        if(transparentGzip1 && "gzip".equalsIgnoreCase(networkResponse.header("Content-Encoding")) && HttpHeaders.hasBody(networkResponse)) {
            GzipSource responseBody = new GzipSource(networkResponse.body().source());
            Headers strippedHeaders = networkResponse.headers().newBuilder().removeAll("Content-Encoding").removeAll("Content-Length").build();
            responseBuilder.headers(strippedHeaders);
            responseBuilder.body(new RealResponseBody(strippedHeaders, Okio.buffer(responseBody)));
        }


        return responseBuilder.build();
    }

BridgeInterceptor类实现了Interceptor接口的intercept(Chain chain)方法。

当进行网络拦截的时候会执行intercept(Chain chain)里面的代码,而这里面把设置了一些系统Header(关于OkHttp如何实现拦截过程不在本文讲述范围)。

继续回顾RealCall类中的execute()方法。这是一个同步的方法,使用的时候需要开启一个子线程进行网络请求,除此之外还有一个异步的方法enqueue(Callback responseCallback)不需要开启子线程当网络访问有结果是会调用Callback 的回掉方法。下面我们看下RealCall类中时如何实现这个方法的,代码如下:

@Override

    public void enqueue(Callback responseCallback) {
        synchronized(this) {
            if(this.executed) {
                throw new IllegalStateException("Already Executed");
            }


            this.executed = true;
        }


        this.client.dispatcher().enqueue(new RealCall.AsyncCall(responseCallback));
    }

继续查看RealCall的内部类AsyncCall的实现:

 final class AsyncCall extends NamedRunnable {
        private final Callback responseCallback;


        private AsyncCall(Callback responseCallback) {
            super("OkHttp %s", new Object[]{RealCall.this.redactedUrl().toString()});
            this.responseCallback = responseCallback;
        }


        String host() {
            return RealCall.this.originalRequest.url().host();
        }


        Request request() {
            return RealCall.this.originalRequest;
        }


        RealCall get() {
            return RealCall.this;
        }

@Override
        protected void execute() {
            boolean signalledCallback = false;

            try {
                Response e = RealCall.this.getResponseWithInterceptorChain();
                if(RealCall.this.retryAndFollowUpInterceptor.isCanceled()) {
                    signalledCallback = true;
                    this.responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
                } else {
                    signalledCallback = true;
                    this.responseCallback.onResponse(RealCall.this, e);
                }
            } catch (IOException var6) {
                if(signalledCallback) {
                    Platform.get().log(4, "Callback failure for " + RealCall.this.toLoggableString(), var6);
                } else {
                    this.responseCallback.onFailure(RealCall.this, var6);
                }
            } finally {
                RealCall.this.client.dispatcher().finished(this);
            }


        }
    }

看到标红的代码可以知道,这里添加了同样的拦截器BridgeInterceptor类。而这些内容是重写的execute()方法里面,我们看下父类NamedRunnable的实现过程:

public abstract class NamedRunnable implements Runnable {
    protected final String name;


    public NamedRunnable(String format, Object... args) {
        this.name = Util.format(format, args);
    }

@Override
    public final void run() {
        String oldName = Thread.currentThread().getName();
        Thread.currentThread().setName(this.name);


        try {
            this.execute();
        } finally {
            Thread.currentThread().setName(oldName);
        }


    }


    protected abstract void execute();
}

由此可以知道NamedRunnable抽象类时实现的Runnable的接口,并定义了一个未实现的方法execute()。而这个方法是在run()方法里面进行调用的。

嗯,整体大概就是这个样子的。

这里没有细说execute()方法和enqueue(Callback responseCallback)方法的区别,刚兴趣的话可以百度下。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值