一、基本概念
1、定义
多个对象都有机会处理请求,将这些对象连成一个链,将请求沿着这条链传递,直到有对象处理为止。
2、使用场景
- 多个对象处理同一请求,具体哪个对象处理需要动态决定
- 需要指定一组对象处理请求
3、优点
- 将处理者和请求者进行解耦
4、缺点
- 需要对处理者进行遍历,处理者过多会影响性能
5、类图
- Handler:抽象处理者,声明请求处理的方法,并保持对下一个处理节点Handler的引用
- ConcreteHandler:具体处理者,对请求进行处理,如果不能处理将请求转发给下一个节点
二、实例
1、抽象类Handler
/**
* @Description 抽象处理者
*/
public abstract class Handler {
//下一个处理者
private Handler mNextHandler;
public Handler(){
}
/**
* 传入下一个处理者
* @param nextHandler
*/
public Handler(Handler nextHandler) {
this.mNextHandler = nextHandler;
}
/**
* 处理请求
*/
public final void handleRequest(Request request) {
//请求者和处理者级别相同才进行处理
if (getCurLevel() == request.getRequestLevel()) {
handle(request);
} else {
//否则将请求交给下一个处理者
if (mNextHandler != null) {
mNextHandler.handleRequest(request);
} else {
System.out.print("无人处理");
}
}
}
/**
* 获取处理者的级别
* @return
*/
protected abstract int getCurLevel();
/**
* 当前处理者处理的逻辑
* @param request
*/
protected abstract void handle(Request request);
}
复制代码
2、具体处理者
public class HandlerA extends Handler {
public HandlerA(Handler nextHandler) {
super(nextHandler);
}
@Override
protected int getCurLevel() {
return 6;
}
@Override
protected void handle(Request request) {
System.out.print("HandlerA 进行处理");
}
}
复制代码
public class HandlerB extends Handler {
public HandlerB() {
}
public HandlerB(Handler nextHandler) {
super(nextHandler);
}
@Override
protected int getCurLevel() {
return 10;
}
@Override
protected void handle(Request request) {
System.out.print("HandlerB 进行处理");
}
}
复制代码
3、抽象请求
public abstract class Request {
/**
* @return 请求的级别
*/
public abstract int getRequestLevel();
}
复制代码
4、具体请求
public class RequestA extends Request {
@Override
public int getRequestLevel() {
return 10;
}
}
复制代码
5、使用
public class HandlerTest {
public static void main(String[] args) {
RequestA request = new RequestA();
//最后一个处理者
Handler handlerB = new HandlerB();
//第一个处理者
Handler handlerA = new HandlerA(handlerB);
//最终传递到HandlerB处理
handlerA.handleRequest(request);
}
}
复制代码
三、OkHttp的Interceptor
纯的责任链模式是如果被处理者进行处理了,则请求传递结束。OkHttp的拦截器是不纯的责任链模式,在请求到达时,拦截器会做一些处理(比如添加参数等),然后传递给下一个拦截器进行处理。
1、请求拦截处理
在请求过程中,通过拦截器对请求进行处理
Response response = getResponseWithInterceptorChain();
复制代码
Response getResponseWithInterceptorChain() throws IOException {
// 创建拦截器的list
List<Interceptor> interceptors = new ArrayList<>();
interceptors.addAll(client.interceptors());
interceptors.add(retryAndFollowUpInterceptor);
interceptors.add(new BridgeInterceptor(client.cookieJar()));
interceptors.add(new CacheInterceptor(client.internalCache()));
interceptors.add(new ConnectInterceptor(client));
if (!forWebSocket) {
interceptors.addAll(client.networkInterceptors());
}
interceptors.add(new CallServerInterceptor(forWebSocket));
// 创建RealInterceptorChain,传入的index索引为0
Interceptor.Chain chain = new RealInterceptorChain(interceptors, null, null, null, 0,
originalRequest, this, eventListener, client.connectTimeoutMillis(),
client.readTimeoutMillis(), client.writeTimeoutMillis());
return chain.proceed(originalRequest);
}
复制代码
创建首个RealInterceptorChain对象,并传入拦截器的集合,通过proceed进行请求的处理。
2、请求处理
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
RealConnection connection) throws IOException {
......
// 创建下一个RealInterceptorChain,将index+1(下一个拦截器索引)传入
RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
writeTimeout);
//获取当前的拦截器
Interceptor interceptor = interceptors.get(index);
//通过Interceptor的intercept进行处理
Response response = interceptor.intercept(next);
......
return response;
}
复制代码
- 创建下一个RealInterceptorChain对象,并将当前RealInterceptorChain中的变量当成参数传入,并将索引index+1传入。
- 获取当前index位置上的拦截器,第一次创建时传入的index为0,表示获取第一个拦截器,后面会将index+1进入传入,用于获取下一个拦截器。
- 在Interceptor的intercept中,将下一个RealInterceptorChain传入,内部会调用下一个RealInterceptorChain的proceed方法
3、Interceptor接口
public interface Interceptor {
/**
* 拦截Chain,并触发下一个拦截器的调用
* @param chain 被处理的对象
* @return
* @throws IOException
*/
Response intercept(Chain chain) throws IOException;
interface Chain {
//返回请求
Request request();
//对请求进行处理
Response proceed(Request request) throws IOException;
......
}
}
复制代码
4、ConnectInterceptor
public final class ConnectInterceptor implements Interceptor {
public final OkHttpClient client;
public ConnectInterceptor(OkHttpClient client) {
this.client = client;
}
@Override public Response intercept(Chain chain) throws IOException {
//下一个拦截链
RealInterceptorChain realChain = (RealInterceptorChain) chain;
//获取Request进行处理
Request request = realChain.request();
StreamAllocation streamAllocation = realChain.streamAllocation();
// We need the network to satisfy this request. Possibly for validating a conditional GET.
boolean doExtensiveHealthChecks = !request.method().equals("GET");
HttpCodec httpCodec = streamAllocation.newStream(client, chain, doExtensiveHealthChecks);
RealConnection connection = streamAllocation.connection();
//会调用下一个拦截链的proceed进行处理
return realChain.proceed(request, streamAllocation, httpCodec, connection);
}
}
复制代码
ConnectInterceptor作为一个具体的处理者,接收到下一个RealInterceptorChain对象,通过RealInterceptorChain的proceed方法对请求进行处理。
整个链式调用的流程为:
首个Chain procced--首个Interceptor interceptor--
下一个Chain procced--下一个Interceptor interceptor--
下一个Chain procced--下一个Interceptor interceptor....