美文网首页
OKhttp使用详解(二)

OKhttp使用详解(二)

作者: WangGavin | 来源:发表于2017-10-11 13:13 被阅读353次

    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使用列表跟踪拦截器,拦截器按顺序调用。

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


    titletitle

    简单实例

    /**
     * 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());

    titletitle

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

    添加网络拦截器

    builder.addInterceptor(new LoggingInterceptor());

    titletitle

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

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

    应用拦截器

    • 不必担心中间响应,如重定向和重试
    • 总是调用一次,即使从缓存中提供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的清洁,轻便的协议缓冲区。

    相关文章

      网友评论

          本文标题:OKhttp使用详解(二)

          本文链接:https://www.haomeiwen.com/subject/ponzjxtx.html