我的环境如下
拦截器应用场景
- 在发送请求前,更改或者添加东西,比如
header 或者 get 的 url 添加「身份认证」
参考资料
内容
回顾一下我们曾经学习过的因特网五层协议栈:
- 网络请求发出时:应用层->传输层->网络层->连接层->物理层
- 收到响应后:物理层->连接层->网络层->传输层->应用层
这个很像我们这次要讲的 okhttp 中的 interceptor 的责任链模式。
Interceptor

Application Interceptor
我们可以自定义设置 Okhttp 的拦截器之一。
从流程图中我们可以看到一次网络请求它只会执行一次拦截,而且它是第一个触发拦截的,这里拦截到的url请求的信息都是最原始的信息。所以我们可以在该拦截器中添加一些我们请求中需要的通用信息,打印一些我们需要的日志。
当然我们可以定义多个这样的拦截器,一个处理 header 信息,一个处理 接口请求的 加解密 。
NetwrokInterceptor
NetwrokInterceptor 也是我们可以自定义的拦截器之一。
它位于倒数第二层,会经过 RetryAndFollowIntercptor 进行重定向并且也会通过 BridgeInterceptor 进行 request请求头和 响应 resposne的处理,因此这里可以得到的是更多的信息。在打印结果可以看到它内部重定向操作和失败重试,这里会有比 Application Interceptor 更多的日志。
RetryAndFollowInterceptor
RetryAndFollowUpInterceptor 的作用,看到该拦截器的名称就知道,它就是一个负责失败重连的拦截器。它是 Okhttp 内置的第一个拦截器,通过 while (true)的死循环来进行对异常结果或者响应结果判断是否要进行重新请求。
BridgeInterceptor
BridgeInterceptor 为用户构建的一个 Request 请求转化为能够进行网络访问的请求,同时将网络请求回来的响应 Response 转化为用户可用的 Response。比如,涉及的网络文件的类型和网页的编码,返回的数据的解压处理等等。
CacheInterceptor
CacheInterceptor 根据 OkHttpClient 对象的配置以及缓存策略对请求值进行缓存。
ConnectInterceptor
ConnectInterceptor 在 OKHTTP 底层是通过 SOCKET 的方式于服务端进行连接的,并且在连接建立之后会通过 OKIO 获取通向 server 端的输入流 Source 和输出流 Sink。
CallServerInterceptor
CallServerInterceptor 在 ConnectInterceptor 拦截器的功能就是负责与服务器建立 Socket 连接,并且创建了一个 HttpStream 它包括通向服务器的输入流和输出流。而接下来的 CallServerInterceptor 拦截器的功能使用 HttpStream 与服务器进行数据的读写操作的。
Interceptor 使用
我主要有以下使用场景
- 增加和修改
header
- 修改
post 的 body
get 请求 变成 post 请求或者反过来
- 重定向
url
- …
SelfInteceptor
我们先创建一个抽象类。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package com.shicuiji.Inteceptor;
import okhttp3.Interceptor; import okhttp3.Request; import okhttp3.Response;
import java.io.IOException;
public abstract class SelfInteceptor implements Interceptor {
@Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); Request.Builder builder = request.newBuilder(); buildSign(request, builder); Request newRequest = builder.build(); return chain.proceed(newRequest); }
public abstract void buildSign(Request request, Request.Builder builder); }
|
其中,buildSign 是来处理上面的各种情况的。
你可以看到在 intercept 这个函数中,主要参数是
从 chain 我们可以得到 request
chain.request()
request.newBuilder()
- 从
request 来获取 builder ,然后用来重构 request
最后使用 chain.proceed(newRequest) 来进行新的 request 请求。
Application
我们建立一个 Application 文件,来使用上面的类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import com.shicuiji.Inteceptor.SelfInteceptor; import okhttp3.*; import org.jetbrains.annotations.NotNull;
import java.io.IOException;
public class Application { public static void main(String[] args) {
OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(new SelfInteceptor() { @Override public void buildSign(Request request, Request.Builder builder) { builder.addHeader("test", "123"); builder.get().url("https://www.bilibili.com/"); } }).build(); String url = "http://www.baidu.com/"; Request request = new Request.Builder().url(url).delete().build(); Call call = okHttpClient.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(@NotNull Call call, @NotNull IOException e) { System.out.println(e); }
@Override public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException { System.out.println(response); } }); } }
|
上面可以看出其做了如下的操作
- 修改
header
- 重定向网址
- 修改请求方式「
get」
我们在来细分一下相关的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import com.shicuiji.Inteceptor.SelfInteceptor; import okhttp3.*; import org.jetbrains.annotations.NotNull;
import java.io.IOException;
public class Application { public static void main(String[] args) {
OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(new SelfInteceptor() { @Override public void buildSign(Request request, Request.Builder builder) { builder.addHeader("test", "123"); } }).build(); ... call.enqueue(new Callback() { ... }); } }
|
修改 post 的 body
get 请求 变成 post 请求或者反过来
GET
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import com.shicuiji.Inteceptor.SelfInteceptor; import okhttp3.*; import org.jetbrains.annotations.NotNull;
import java.io.IOException;
public class Application { public static void main(String[] args) {
OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(new SelfInteceptor() { @Override public void buildSign(Request request, Request.Builder builder) { builder.get(); } }).build(); ... call.enqueue(new Callback() { ... }); } }
|
POST
重定向 url
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import com.shicuiji.Inteceptor.SelfInteceptor; import okhttp3.*; import org.jetbrains.annotations.NotNull;
import java.io.IOException;
public class Application { public static void main(String[] args) {
OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(new SelfInteceptor() { @Override public void buildSign(Request request, Request.Builder builder) { builder.url("https://www.bilibili.com/"); } }).build(); ... call.enqueue(new Callback() { ... }); } }
|