拦截器

Java里的拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行,同时也提供了一种可以提取action中可重用部分的方式。
在AOP(Aspect-Oriented Programming)中拦截器用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。

过滤器

过滤器可以简单理解为“取你所想取”,忽视掉那些你不想要的东西;拦截器可以简单理解为“拒你所想拒”,关心你想要拒绝掉哪些东西,比如一个BBS论坛上拦截掉敏感词汇。

1.拦截器是基于java反射机制的,而过滤器是基于函数回调的。
2.过滤器依赖于servlet容器,而拦截器不依赖于servlet容器。
3.拦截器只对action起作用,而过滤器几乎可以对所有请求起作用。
4.拦截器可以访问action上下文、值栈里的对象,而过滤器不能。
5.在action的生命周期里,拦截器可以多起调用,而过滤器只能在容器初始化时调用一次。
Android里面过滤器大家用的已经无法再陌生了,Filter就是一个很好的列子,在清单文件注册Filter就可以过滤启动摸某个组件的Action.

Okhttp拦截器因此应运而生,处理一次网络调用的Action拦截,做修改操作。

OKHTTP INTERCEPTOR

使用

okhttp拦截器用法很简单,构建OkHttpClient时候通过.addInterceptor()就可以将拦截器加入到一次会话中。

OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new LoggingInterceptor())
.build();
1
2
3
1
2
3
拦截器

拦截器是Okhttp一种强大的机制,可以监视,重写和重试每一次请求。下面示列了一个简单的拦截器,用于记录传出的请求和传入的响应。

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;
}
}
呼叫chain.proceed(request)是每个拦截器实现的关键部分。这个简单的方法是所有HTTP工作发生的地方,产生满足请求的响应。

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

应用拦截器

拦截器被注册为应用程序或网络拦截器。我们将使用LoggingInterceptor上面定义来显示差异。

注册一个应用程序通过调用拦截器addInterceptor()上OkHttpClient.Builder:

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();
URLhttp://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()。两个日志语句记录两个不同的URL。

网络拦截器

注册网络拦截器是非常相似的。调用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/ www.tengxun10001.cn 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
网络请求还包含更多的数据,例如Accept-Encoding: gzip由OkHttp添加的标题来广播支持响应压缩。网络拦截器Chain具有非空值Connection,可用于询问用于连接到Web服务器的IP地址和TLS配置。

在应用拦截器和网络拦截器之间如何让进行选择?

每个拦截链有相对优点。

应用拦截器

不需要担心中间响应,如重定向和重试。
总是调用一次,即使从缓存提供HTTP响应。
遵守应用程序的原始意图。不注意OkHttp注入的头像If-None-Match。
允许短路和不通话Chain.proceed()。
允许重试并进行多次呼叫Chain.proceed()。
网络拦截器

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

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

final class GzipRequestInterceptor implements Interceptor {
@Override public Response intercept(Interceptor.Chain chain) throws IOException {
Request originalRequest = chain.request();
if (originalRequest.body() == null |www.jnd3658.cn| 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响应头以启用更好的响应缓存:

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(www.vboyl130.cn)
.header("Cache-Control", "max-age=60")
.build();
}
};
通常,这种方法在补充Web服务器上的相应修复程序时效果最好!

转载于:https://www.cnblogs.com/chenergougou/p/7116593.html

OkHttp 3.x 源码解析之Interceptor 拦截器相关推荐

  1. OkHttp 3.x 源码解析之Dispatcher分发器

    Dispatcher概念 Dispatcher中文是分发器的意思,和拦截器不同的是分发器不做Aaction事件处理.只做事件流向.在Okhttp中Dispatcher负责将每一次Requst进行分发, ...

  2. Spring MVC源码解析——HandlerMapping(处理器映射器)

    Sping MVC 源码解析--HandlerMapping处理器映射器 1. 什么是HandlerMapping 2. HandlerMapping 2.1 HandlerMapping初始化 2. ...

  3. [源码解析] PyTorch分布式优化器(1)----基石篇

    [源码解析] PyTorch分布式优化器(1)----基石篇 文章目录 [源码解析] PyTorch分布式优化器(1)----基石篇 0x00 摘要 0x01 从问题出发 1.1 示例 1.2 问题点 ...

  4. postgres 源码解析25 缓冲池管理器-3

      本文讲解缓冲块的选择策略BufferAlloc,同时该函数也是替换策略的核心函数, 知识回顾: postgres源码解析 缓冲池管理–1 postgres源码解析 缓冲池管理–2 总结<执行 ...

  5. postgres 源码解析11 CLOG管理器--2

      在本小节中,着重讲解CLOG日志的读写操作,获取事务的状态信息进行可见性判断内容,相关背景知识见回顾通道: 1 postgres CLOG源码解析-1 2 postgres源码分析 Slru缓冲池 ...

  6. Google guava cache源码解析1--构建缓存器(2)

    此文已由作者赵计刚授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. CacheBuilder-->maximumSize(long size) /*** 指定cache中 ...

  7. postgres 源码解析9 CLOG管理器--1

    1 背景介绍   在Postgres数据库的日志管理系统中,采用CLOG日志记录集群中每个事务的最终状态,在内存中形式是基于SLRU缓冲实现的,有兴趣的回顾下SLRU相关知识:   1 postgre ...

  8. OkHttp3源码详解(三) 拦截器-RetryAndFollowUpInterceptor

    最大恢复追逐次数: private static final int MAX_FOLLOW_UPS = 20; 处理的业务: 实例化StreamAllocation,初始化一个Socket连接对象,获 ...

  9. Google guava cache源码解析1--构建缓存器(3)

    此文已由作者赵计刚授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 下面介绍在LocalCache(CacheBuilder, CacheLoader)中调用的一些方法: Ca ...

最新文章

  1. 【数理知识】《随机过程》方兆本老师-第6章-鞅过程及其性质
  2. DayDayUp:分析“普通人”如何逐步走上食物链顶端(看那些成名史案例,有感而发)
  3. Winform中设置ZedGraph的X轴的刻度根据曲线获取
  4. sql去除空值_SQL汇总分析
  5. JSP页面的继承(extends)
  6. 语句include和require的区别是什么?
  7. Android eclipse导入项目后出现Unable to resolve target #39;android-17#39;解决方法
  8. 已知网友建立html,职称计算机模拟试题:Dreamweaver网页设计模拟试题及答案(5)...
  9. IOS10.8.2安装
  10. iOS 开发常用链接总结
  11. caffe FCN Ubuntu16.0
  12. JAVA后端开发的一些工作经验
  13. 变种水仙花数 - Lily Number
  14. Python语言程序设计基础_实验四_函数(一)_答案_通识教育必修课程_上海师范大学
  15. 免疫系统与冠状病毒之争:抗体水平下降时,T细胞会支持你
  16. 什么是电口模块?它和光模块有什么区别?
  17. 协议森林05 我尽力 (IP协议详解)
  18. java毕业设计springboot框架 java二手交易网站系统毕业设计开题报告功能参考
  19. 10岁娃获“信息学奥赛”省一等奖
  20. 如何诊断Shopee店铺?记住这3个操作

热门文章

  1. div没有设置高度,背景颜色却无法显示
  2. 深入浅析HTML5中的article和section的区别
  3. 【重要】ES6-23 JavaScript模块化
  4. 阿里云ecs实例中创建数据库
  5. JavaScript的值传递和引用传递
  6. Linux编程 3 (初识bash shell与man查看手册)
  7. Java核心技术及面试指南 异常部分的面试题归纳以及答案
  8. 代码生成工具之界面快速生成
  9. C#学习笔记:预处理指令
  10. Oracle查询和解锁表