0%

OkHttp | 拦截器(Interceptor)

我的环境如下

  • okhttp3:okhttp:4.7.2

拦截器应用场景


  • 在发送请求前,更改或者添加东西,比如 header 或者 geturl 添加「身份认证」

参考资料



内容


回顾一下我们曾经学习过的因特网五层协议栈:

  • 网络请求发出时:应用层->传输层->网络层->连接层->物理层
  • 收到响应后:物理层->连接层->网络层->传输层->应用层

这个很像我们这次要讲的 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

ConnectInterceptorOKHTTP 底层是通过 SOCKET 的方式于服务端进行连接的,并且在连接建立之后会通过 OKIO 获取通向 server 端的输入流 Source 和输出流 Sink

CallServerInterceptor

CallServerInterceptorConnectInterceptor 拦截器的功能就是负责与服务器建立 Socket 连接,并且创建了一个 HttpStream 它包括通向服务器的输入流和输出流。而接下来的 CallServerInterceptor 拦截器的功能使用 HttpStream 与服务器进行数据的读写操作的。

Interceptor 使用

我主要有以下使用场景

  • 增加和修改 header
  • 修改 postbody
  • 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

chain 我们可以得到 request

  • chain.request()
    • 获取 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

我们在来细分一下相关的使用

增加和修改 header

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() {
...
});
}
}

修改 postbody

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() {
...
});
}
}
请我喝杯咖啡吧~