OkHttp3源码(二)------Request

上篇OkHttp3源码(一)——OkHttpClient很荣幸得到评论加关注。

Request —— 是对HTTP请求报文概念的具体实现
请求报文的结构图
这里写图片描述

根据结构图去阅读源码能很好的理解某些属性的真实意义。

我们看一下源码。

public final class Request {
    final HttpUrl url;
    final String method;
    final Headers headers;
    final RequestBody body;
    final Object tag;
    private volatile CacheControl cacheControl; // Lazily initialized.

    Request(Builder builder) {
        this.url = builder.url;
        this.method = builder.method;
        this.headers = builder.headers.build();
        this.body = builder.body;
        this.tag = builder.tag != null ? builder.tag : this;
    }
    //返回设置的URL
    public HttpUrl url() {
        return url;
    }
    //返回设置的方法  get或post
    public String method() {
        return method;
    }
    //返回所有的头部对象(这里的对象可以理解为一个键值对)
    public Headers headers() {
        return headers;
    }
    //返回头部名称为name的信息
    public String header(String name) {
        return headers.get(name);
    }
    //返回头部所有名称为name的信息
    public List<String> headers(String name) {
        return headers.values(name);
    }
    //返回请求体
    public RequestBody body() {
        return body;
    }
    //返回设置的请求标签
    public Object tag() {
        return tag;
    }
    //根据自身设置的参数重新构造对象
    public Builder newBuilder() {
        return new Builder(this);
    }
    //根据在头部设置的与缓存有关的信息,返回缓存控制器,
    public CacheControl cacheControl() {
        CacheControl result = cacheControl;
        return result != null ? result : (cacheControl = CacheControl.parse(headers));
    }
    //是否用的HTTPS协议
    public boolean isHttps() {
        return url.isHttps();
    }

    /**
     * 接下来就是Builder设计模式
     * OkHttp用的比较多的设计模式
     * 对Builder模式不了解的,先去了解下。这里概括一下Builder模式:类的某些字段无法通过自身去赋值,需要委托给其他类去赋值。
     */
    public static class Builder {
        HttpUrl url;
        String method;
        Headers.Builder headers;
        RequestBody body;
        Object tag;

        //由这里可以看出Request的默认请求方式是“GET”,且header为空
        public Builder() {
            this.method = "GET";
            this.headers = new Headers.Builder();
        }
        //根据Resquest已设置的参数重新创建对象
        Builder(Request request) {
            this.url = request.url;
            this.method = request.method;
            this.body = request.body;
            this.tag = request.tag;
            this.headers = request.headers.newBuilder();
        }
        //设置HttpUrl,这里就省去了对String url 内容的封装。
        public Builder url(HttpUrl url) {
            if (url == null) throw new NullPointerException("url == null");
            this.url = url;
            return this;
        }

        //设置url, 这里需要对String url的内容封装成HttpUrl。
        public Builder url(String url) {
            if (url == null) throw new NullPointerException("url == null");

            // Silently replace web socket URLs with HTTP URLs.
            if (url.regionMatches(true, 0, "ws:", 0, 3)) {
                url = "http:" + url.substring(3);
            } else if (url.regionMatches(true, 0, "wss:", 0, 4)) {
                url = "https:" + url.substring(4);
            }

            HttpUrl parsed = HttpUrl.parse(url);
            if (parsed == null) throw new IllegalArgumentException("unexpected url: " + url);
            return url(parsed);
        }

       //设置URL,其实内部的实现与String url相同。
        public Builder url(URL url) {
            if (url == null) throw new NullPointerException("url == null");
            HttpUrl parsed = HttpUrl.get(url);
            if (parsed == null) throw new IllegalArgumentException("unexpected url: " + url);
            return url(parsed);
        }

        //设置一个头部信息(键值对的形式),并将与此name相同的头部信息全部清除。
        public Builder header(String name, String value) {
            headers.set(name, value);
            return this;
        }
        //添加一个头部信息(键值对的形式),这里这是不用清除其他头部信息
        public Builder addHeader(String name, String value) {
            headers.add(name, value);
            return this;
        }
        //清除所有头部名称为name的信息
        public Builder removeHeader(String name) {
            headers.removeAll(name);
            return this;
        }
        //设置头部对象
        public Builder headers(Headers headers) {
            this.headers = headers.newBuilder();
            return this;
        }

        //设置将缓存控制器里面设置的信息添加到头部
        public Builder cacheControl(CacheControl cacheControl) {
            String value = cacheControl.toString();
            if (value.isEmpty()) return removeHeader("Cache-Control");
            return header("Cache-Control", value);
        }
        //设置get方法并且请求体为null
        public Builder get() {
            return method("GET", null);
        }
        //设置post方法并且请求体不能为null
        public Builder post(RequestBody body) {
            return method("POST", body);
        }
        //设置方法,如果方法有请求体,必须设置请求体
        public Builder method(String method, RequestBody body) {
            if (method == null) throw new NullPointerException("method == null");
            if (method.length() == 0) throw new IllegalArgumentException("method.length() == 0");
            if (body != null && !HttpMethod.permitsRequestBody(method)) {
                throw new IllegalArgumentException("method " + method + " must not have a request body.");
            }
            if (body == null && HttpMethod.requiresRequestBody(method)) {
                throw new IllegalArgumentException("method " + method + " must have a request body.");
            }
            this.method = method;
            this.body = body;
            return this;
        }

        //设置当前请求体的标签
        public Builder tag(Object tag) {
            this.tag = tag;
            return this;
        }
        //创建Request对象。
        public Request build() {
            if (url == null) throw new IllegalStateException("url == null");
            return new Request(this);
        }
    }
}

通过上面的注释分析我们知道:
Request类主要配置网络请求的请求体,
相关参数有HttpUrl、method、Headers、RequestBody、CacheControl。
对于除method以外的其他参数类,都是对网络请求的请求体相关信息的封装。
我们后面会解释Headers、RequestBody、CacheControl三个类。

猜你喜欢

转载自blog.csdn.net/look_Future/article/details/79698793