之拦截器

Note:在自个儿翻译那篇小说的时候OKHttp的版本是3.6.0。那个连串的文章介绍了非常多英特网教程比相当少的拦截器,介绍了什么样兑现拦阻乞求

OKHttp(一)之Calls

OKHttp之Calls

OKHttp(二)之Connections

OKHttp之Connections

OkHttp(三)之使用格局

OkHttp之使用办法

OkHttp(四)之拦截器

OkHttp之拦截器

OkHttp(五)之HTTPS

OkHttp之HTTPS

Retrofit使用详解(一)

Retrofit使用详解

Retrofit使用详解(二)

Retrofit使用详解

Retrofit使用详解(三)

Retrofit使用详解

Retrofit使用详解(四)

Retrofit使用详解

Retrofit使用详解(五)

Retrofit使用详解

Retrofit使用详解(六)

Retrofit使用详解

拦截器(Interceptor)是一个庞大的工具,(在上方的自家翻译的retrofit教程中列出了何等行使拦截器为呼吁增加认证token,即使token过期刷新token的篇章作者还没写,有意思味的同桌能够留言)他能够监视,重写,重试你的call,上面是贰个简约的例子,自定义了一个拦截器达成了发生的呼吁和收取的响应的日记打字与印刷:

HTTP客商端的天职是承受你的伸手并发出响应。 那在评论上很轻巧,但在执行中却很讨厌。

class LoggingInterceptor implements Interceptor {
  @Override public Response intercept(Interceptor.Chain chain) throws IOException {
    Request request = chain.request();

    long t1 = System.nanoTime();
    logger.info(String.format("Sending request %s on %s%n%s",
        request.url(), chain.connection(), request.headers()));

    Response response = chain.proceed(request);

    long t2 = System.nanoTime();
    logger.info(String.format("Received response for %s in %.1fms%n%s",
        response.request().url(), (t2 - t1) / 1e6d, response.headers()));

    return response;
  }
}

种种HTTP乞请()包括三个U奥迪Q5L,二个格局(比如GET只怕POST),和贰个头音讯列表。央浼也许会含有三个哀告体:一种特定项目标数据流(一般是JSON格式)。

对chain.proceed(request)的调用是拦截器达成的机要部分。

一呼百应是呼吁的一种回复,满含状态码(200表示成功,404象征未找到该页),头音信和响应体。

拦截器能够链接。要是你有三个缩减拦截器和三个反省结果拦截器,你须要调控拦截器调用的依次。OkHttp使用列表形式来追踪拦截器,拦截器会按您的编纂顺序调用。

当你想OkHttp发送HTTP须要时,你是在八个较高的等第上陈述三个伸手:利用这几个头音信抓取那么些页面包车型大巴多少。为了科学和较高的成效,OkHttp会在出殡和埋葬在此之前重写那一个央求。

图片 1

OkHttp会在本来央浼体上增添缺乏的头新闻,包涵Content-Length, Transfer-Encoding, User-Agent, Host, Connection, 和Content-Type。它将为transparent response compression增添三个Accept-Encoding头,除非头已经存在。 若是您有Cookie,OkHttp将增添贰个Cookie头。

前后相继拦截器

拦截器分为程序拦截器和网络拦截器。来看看上面定义的LoggingInterceptor来显示双方的分裂。

因而在OkHttpClient.Builder上调用addInterceptor()来注册应用程序拦截器:

OkHttpClient client = new OkHttpClient.Builder()
    .addInterceptor(new LoggingInterceptor())
    .build();

Request request = new Request.Builder()
    .url("http://www.publicobject.com/helloworld.txt")
    .header("User-Agent", "OkHttp Example")
    .build();

Response response = client.newCall(request).execute();
response.body().close();

网址http://www.publicobject.com/helloworld.txt重定向到https://publicobject.com/helloworld.txt,OkHttp会自动追踪此重定向。 咱们的应用程序拦截器被调用一回,并且从chain.proceed()重回的响应拥有重定向响应,以下是打字与印刷日志

INFO: Sending request http://www.publicobject.com/helloworld.txt on null
User-Agent: OkHttp Example

INFO: Received response for https://publicobject.com/helloworld.txt in 1179.7ms
Server: nginx/1.4.6 (Ubuntu)
Content-Type: text/plain
Content-Length: 1759
Connection: keep-alive

咱俩得以看来发出伏乞后被重定向,因为response.request().url不一致于request.url。那五个日志语句记录了八个不一致的UEscortL。

少数诉求将有二个缓存响应。 当那些缓存的响应过时时,OkHttp能够做叁个准则GET来下载更新的响应。 那亟需增添如If-Modified-Since和If-None-Match的头。

网络拦截器

挂号网络拦截器和登记程勋拦截器极其相像。用addNetworkInterceptor()方法庖代addInterceptor()方法就能够:

OkHttpClient client = new OkHttpClient.Builder()
    .addNetworkInterceptor(new LoggingInterceptor())
    .build();

Request request = new Request.Builder()
    .url("http://www.publicobject.com/helloworld.txt")
    .header("User-Agent", "OkHttp Example")
    .build();

Response response = client.newCall(request).execute();
response.body().close();

当我们运营上述代码时,拦截器会施行一遍。二遍是在伸手网址http://www.publicobject.com/helloworld.txt的时候,贰回是在被重定向到https://publicobject.com/helloworld.txt的时候。日志如下

INFO: Sending request http://www.publicobject.com/helloworld.txt on Connection{www.publicobject.com:80, proxy=DIRECT hostAddress=54.187.32.157 cipherSuite=none protocol=http/1.1}
User-Agent: OkHttp Example
Host: www.publicobject.com
Connection: Keep-Alive
Accept-Encoding: gzip

INFO: Received response for http://www.publicobject.com/helloworld.txt in 115.6ms
Server: nginx/1.4.6 (Ubuntu)
Content-Type: text/html
Content-Length: 193
Connection: keep-alive
Location: https://publicobject.com/helloworld.txt

INFO: Sending request https://publicobject.com/helloworld.txt on Connection{publicobject.com:443, proxy=DIRECT hostAddress=54.187.32.157 cipherSuite=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA protocol=http/1.1}
User-Agent: OkHttp Example
Host: publicobject.com
Connection: Keep-Alive
Accept-Encoding: gzip

INFO: Received response for https://publicobject.com/helloworld.txt in 80.9ms
Server: nginx/1.4.6 (Ubuntu)
Content-Type: text/plain
Content-Length: 1759
Connection: keep-alive

互连网须求满含更多数据,举例OkHttp加多的Accept-Encoding:gzip头,以宣布对响应压缩的支持。 网络拦截器的Chain有叁个非空连接,可用来查询用于连接到Web服务器的IP地址和TLS配置。

万一使用transparent response compression,OkHttp将去除相应的响应头Content-Encoding和Content-Length,因为它们不适用于解压缩的响应大旨。

选择程序拦截器还是网络拦截器

种种拦截器的帮助和益处是争持的:

借使基准GET成功,则来自互联网和缓存的响应依据标准的提醒统一。

前后相继拦截器

  • 无需忧郁中间响应(如重定向和重试)
  • 只调用叁遍,尽管HTTP响应是从缓存读取的
  • 坚守应用程序原始的用意,不关注OkHttp注入的头音讯,比如If-None-Match
  • 同意短路,不调用Chain.proceed()
  • 允许重试并对五个Chain.proceed()调用

当您诉求的URAV4l地址被移除了,网络服务器会回去二个响应码来代表新的地方。OkHttp会自动重定向到新鸿基土地资金财产点并重启央浼。

网路拦截器

  • 能够对中间响应(如重定向和重试)进行操作。
  • 不调用缓存响应使互连网不通。
  • 考查数据,就好像它将透过互联网传输一样。
  • 可见访谈引导诉求的延续。

比如响应发出授权质询,OkHttp将须要认证者来满足质询。 假若认证者提供证据,则使用带有该证据的重试央求。

重写需要

拦截器能够增添、移除大概替换诉求的头新闻,也足以转移诉求体。比如,若是你正在呼吁三个体协会助压缩的网址,你能够选拔程序拦截器来增加多少个诉求体压缩。

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

一些景色下链接会中断:池连接已不达时宜和已断开连接,或不可能采访Web服务器。 OkHttp将应用分裂的路由重试诉求。

重写响应

拦截器也能够重写响应头天公地道写响应体,不过这么一般比例写诉求头更危险,因为它只怕违反互连网合同。

固然您正处在贰个棘手的图景,并计划管理大概发生的结局,重写响应头是缓和难题的章程。比方,你能够秀谷服务器配置错的的缓存调控响应头译启用更加好的响应缓存:

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

习认为常,这种艺术在补偿Web服务器上的应和修复时坚守最棒!

透过重写,重定向,跟进和重试,你的粗略央浼也许会发生众多呼吁和响应。 OkHttp使用Call来建立模型知足你的乞请的职分,相当多当中需要和响应是须求的。 可是,假诺你的U大切诺基L重定向或然您转移到备用IP地址,您的代码将继续职业。

可用性

OkHttp的拦截器需求OkHttp 2.2或越来越高版本。拦截器无法利用OkUrlFactory或营造它的库,包蕴Retrofit≤1.8和Picasso≤2.4。

调用以两种办法之一实行

- 同步:你的线程阻塞,直到响应可读。- 异步:将请求排入任何线程,并在响应可读时在另一个线程上调用。

能够从别的线程撤销调用。 如果未能如愿,调用失利! 正在写诉求主体或读取响应中央的代码,就要其调用撤除时发出IOException。

对于联合调用,使用自个儿的线程,并担当管理同一时候发生多少央求。 太多的一路三回九转浪费财富并会延迟。

对此异步调用,Dispatcher完成最大出现恳求的政策。 您可以设置每一种互连网服务器的最大值和总体值。

本文由华夏彩票发布于编程应用,转载请注明出处:之拦截器

您可能还会对下面的文章感兴趣: