多個對象都有機會處理請求,將這些對象連成一個鏈,將請求沿着這條鏈傳遞,直到有對象處理爲止。bash
/**
* @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);
}
複製代碼
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 進行處理");
}
}
複製代碼
public abstract class Request {
/**
* @return 請求的級別
*/
public abstract int getRequestLevel();
}
複製代碼
public class RequestA extends Request {
@Override
public int getRequestLevel() {
return 10;
}
}
複製代碼
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的攔截器是不純的責任鏈模式,在請求到達時,攔截器會作一些處理(好比添加參數等),而後傳遞給下一個攔截器進行處理。cookie
在請求過程當中,經過攔截器對請求進行處理ide
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進行請求的處理。性能
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;
}
複製代碼
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;
......
}
}
複製代碼
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....ui