我的环境如下
拦截器应用场景
- 在发送请求前,更改或者添加东西,比如
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() { ... }); } }
|