OKhttp使用详解(二)

Cookie保存

Cookie的保存也提供了快捷方式,当然也可以通过拦截器自己实现

OkHttpClient okHttpClient = new OkHttpClient.Builder()
              .cookieJar(new CookieJar() {
                  @Override
                  public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
                // 保存cookie通常使用SharedPreferences
                  }

                  @Override
                  public List<Cookie> loadForRequest(HttpUrl url) {
                    // 从保存位置读取,注意此处不能为空,否则会导致空指针
                      return new ArrayList<>();
                  }
              })
              .build();

Websocket

okhttp3支持websocket,如果不了解请自行搜索,简易推送,轮训都可以使用。websocket协议首先会发起http请求,握手成功后,转换协议保持长连接,类似心跳

// 方法可以选择实现
OkHttpClient okHttpClient = new OkHttpClient.Builder()
        .build();
Request request = new Request.Builder()
        .url("https://wwww.xxx.com")
        .build();
okHttpClient.newWebSocket(request, new WebSocketListener() {
    @Override
    public void onMessage(WebSocket webSocket, String text) {
        super.onMessage(webSocket, text);
      // 当收到文本消息
    }

    @Override
    public void onOpen(WebSocket webSocket, Response response) {
        super.onOpen(webSocket, response);
       // 连接成功
    }

    @Override
    public void onMessage(WebSocket webSocket, ByteString bytes) {
        super.onMessage(webSocket, bytes);
       // 收到字节消息,可转换为文本
    }

    @Override
    public void onClosed(WebSocket webSocket, int code, String reason) {
        super.onClosed(webSocket, code, reason);
       // 连接被关闭
    }

    @Override
    public void onFailure(WebSocket webSocket, Throwable t, Response response) {
        super.onFailure(webSocket, t, response);
       // 连接失败
    }
});

拦截器 Intercepter

拦截器是一种强大的机制,可以监视,重写和重试呼叫。这是一个简单的拦截器,用于记录传出的请求和传入的响应。

对chain.proceed(request)的调用是每个拦截器实现的关键部分。这个简单的方法是所有HTTP工作发生的地方,产生一个满足请求的响应。

拦截器可以链接。假设您同时拥有一个压缩拦截器和一个校验和拦截器:您需要确定数据是否被压缩,然后进行校验和,或校验和然后压缩。OkHttp使用列表跟踪拦截器,拦截器按顺序调用。

OKhttp使用详解(二)

怎么说呢,这拦截器应该就是面向切面了,反正我觉得很像。一般我们在拦截器里进行log打印,便于开发调试吧。正如图上所示,分为应用拦截器和网络拦截器,当然实质就是对拦截到的请求和响应进行处理,应该类似传说中的网络爬虫吧。


OKhttp使用详解(二)
title

简单实例

/**
 * Created by Newtrek on 2017/5/7.
 */
public class LoggingInterceptor implements Interceptor {
//    自定义拦截器就实现拦截器接口就行
    @Override
    public Response intercept(Chain chain) throws IOException {
//        对chain操作,我查看了下字典Chain是链子的意思,我的理解是这个方法体里相当于链子的断点切面吧,
//        切面里啥内容都有,就看我们怎么处理
        Request request=chain.request();//获取请求
        long t1=System.nanoTime();//开始发送请求的时间
        System.out.println("请求信息:发送时间》"+t1+"  >>"+chain.connection()+" headers>>"+request.headers());
        Response  response=chain.proceed(request);
        long t2=System.nanoTime();
        System.out.println("花费时间:"+(t2-t1)+"响应信息》》");
        return response;
    }
}

添加应用拦截器

builder.addInterceptor(new LoggingInterceptor());

OKhttp使用详解(二)
title

可以验证
先打印的拦截设置的内容,然后才是正常响应处理结果

添加网络拦截器

builder.addInterceptor(new LoggingInterceptor());

OKhttp使用详解(二)
title

我们可以看到网络拦截器有更多的信息,还有网页有重定向的话,可能会对此调用网络拦截器

应用拦截器和网络拦截器的优点

应用拦截器

  • 不必担心中间响应,如重定向和重试
  • 总是调用一次,即使从缓存中提供HTTP响应。
  • 遵守应用程序的原始意图。不注意OkHttp注入的标题,如If-None-Match。
  • 允许短路,不调用Chain.proceed()。
  • 允许重试并多次调用Chain.proceed()。

网路拦截器

  • 能够对重定向和重试等中间响应进行操作。
  • 对于缓存网络短路的响应不被调用。
  • 观察数据,就像通过网络传输一样。
  • 访问携带请求的连接。

重写请求

拦截器可以添加,删除或替换请求标头。他们还可以转换具有一个请求的正文。例如,如果您连接到已知支持它的Web服务器,则可以使用应用程序拦截器添加请求体压缩。

/** This interceptor compresses the HTTP request body. Many webservers can't handle this! */
final class GzipRequestInterceptor implements Interceptor {
  @Override public Response intercept(Interceptor.Chain chain) throws IOException {
    Request originalRequest = chain.request();
    if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) {
      return chain.proceed(originalRequest);
    }

    Request compressedRequest = originalRequest.newBuilder()
        .header("Content-Encoding", "gzip")
        .method(originalRequest.method(), gzip(originalRequest.body()))
        .build();
    return chain.proceed(compressedRequest);
  }

  private RequestBody gzip(final RequestBody body) {
    return new RequestBody() {
      @Override public MediaType contentType() {
        return body.contentType();
      }

      @Override public long contentLength() {
        return -1; // We don't know the compressed length in advance!
      }

      @Override public void writeTo(BufferedSink sink) throws IOException {
        BufferedSink gzipSink = Okio.buffer(new GzipSink(sink));
        body.writeTo(gzipSink);
        gzipSink.close();
      }
    };
  }
}

重写响应

对称地,拦截器可以重写响应头并转换响应体。这通常比重写请求头更危险,因为它可能违反了网络服务器的期望!

例如,您可以修复服务器配置错误的Cache-Control响应头以实现更好的响应缓存:

/** Dangerous interceptor that rewrites the server's cache-control header. */
private static final Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() {
  @Override public Response intercept(Interceptor.Chain chain) throws IOException {
    Response originalResponse = chain.proceed(chain.request());
    return originalResponse.newBuilder()
        .header("Cache-Control", "max-age=60")
        .build();
  }
};

可用性

OkHttp的拦截器需要OkHttp2.2或更高。不幸的是,拦截器不能与OkUrlFactory或其上构建的库一起使用,包括Retrofit≤1.8和Picasso≤2.4。

HTTPS

特定安全性与连接性决定由ConnectionSpec实现。 OkHttp包含三个内置的连接规范:

  • MODERN_TLS是连接到现代HTTPS服务器的安全配置。
  • COMPATIBLE_TLS是连接到安全但不是当前HTTPS服务器的安全配置。
  • CLEARTEXT是用于http:// URL的不安全配置。

默认情况下,OkHttp将尝试MODERN_TLS连接,如果现代配置失败,则返回COMPATIBLE_TLS连接。

例:

ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)  
    .tlsVersions(TlsVersion.TLS_1_2)
    .cipherSuites(
          CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
          CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
          CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
    .build();

OkHttpClient client = new OkHttpClient.Builder() 
    .connectionSpecs(Collections.singletonList(spec))
    .build();

信任固定

默认情况下,OkHttp信任主机平台的证书颁发机构。这种策略最大限度地提高连接性,但是受到2011年DigiNotar攻击的证书颁发机构攻击。它还假设您的HTTPS服务器的证书由证书颁发机构签署。

 client = new OkHttpClient.Builder()
        .certificatePinner(new CertificatePinner.Builder()
            .add("publicobject.com", "sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=")
            .build())
        .build();

自定义受信任的证书

 private final OkHttpClient client;

  public CustomTrust() {
    SSLContext sslContext = sslContextForTrustedCertificates(trustedCertificatesInputStream());
    client = new OkHttpClient.Builder()
        .sslSocketFactory(sslContext.getSocketFactory())
        .build();
  }

  public void run() throws Exception {
    Request request = new Request.Builder()
        .url("https://publicobject.com/helloworld.txt")
        .build();

    Response response = client.newCall(request).execute();
    System.out.println(response.body().string());
  }

  private InputStream trustedCertificatesInputStream() {
    ... // Full source omitted. See sample.
  }

  public SSLContext sslContextForTrustedCertificates(InputStream in) {
    ... // Full source omitted. See sample.
  }
Contact GitHub API Training Shop Blog About
© 2017 GitHub, Inc. Terms Privacy 

与Okhttp3合作使用

说明都在链接上
https://github.com/square/okhttp/wiki/Works-with-OkHttp
我放几个比较常用的

  • Chuck 一个android HTTP客户端 http检查器 star 2k+
  • Fresco 一个用于管理图像和他们使用的内存的Android库start 12K+。https://www.fresco-cn.org/docs/using-other-network-layers.html
  • Glide Android的图像加载和缓存库专注于平滑滚动 star 15K+
  • Moshi json解析库 2.6K+
  • Ok2Curl 就是一个拦截器,方便打印日志
  • okhttp-digedt okhttp的摘要验证器
  • okhttp-signpost 用于签署OkHttp请求的Signpost扩展。
  • Oklog 一个方便查看log的库
  • PersistentCookieJar 基于SharedPreferences的OkHttp 3的持久CookieJar实现。
  • picasso Android的功能强大的图像下载和缓存库 13.3K+
  • Retrofit Square and Inc.的Android和Java类型安全HTTP客户端 20.9K+
  • Stetho Stetho是Android应用程序的复杂调试桥。启用后,开发人员可以访问Chrome浏览器工具功能,而Chrome浏览器桌面浏览器的本地部分。开发人员还可以选择启用可选的dumpapp工具,该工具为应用程序内部构件提供强大的命令行界面。7.5K+
  • wire 用于Android和Java的清洁,轻便的协议缓冲区。
上一篇:day1 View的事件机制


下一篇:JNI学习笔记之ndk-build手动编译并集成流程