1. Basic Concepts

1, define,

Multiple objects have the opportunity to process the request, and the objects are connected in a chain, passing the request along the chain until there is an object to process it.

2. Application scenarios

  • Multiple objects process the same request, and which object to process needs to be determined dynamically
  • You need to specify a set of objects to handle requests

3, strengths,

  • Decouple the handler from the requester

4 and disadvantages

  • Handlers need to be traversed, and too many handlers can affect performance

5, the class diagram

  • Handler: Abstract Handler that declares the method to request processing and maintains a reference to the next processing node, Handler
  • ConcreteHandler: ConcreteHandler that processes the request and forwards it to the next node if it cannot handle it

Second, the instance

1, abstract class Handler

/** * @description public abstract class Handler {// NextHandler private Handler; publicHandlerPublic Handler(Handler nextHandler) {this.mNexthandler = nextHandler; } public final void handleRequest(Request Request)if (getCurLevel() == request.getRequestLevel()) {
      handle(request);
    } else{// Otherwise pass the request to the next handlerif(mNextHandler ! = null) { mNextHandler.handleRequest(request); }else {
        System.out.print("Unattended"); }}} /** * gets the handler level * @return*/ protected abstract int getCurLevel(); /** * @param request */ protected void handle(request request); }Copy the code

2. Specific handlers

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 for processing"); }}Copy the code
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 does the processing."); }}Copy the code

3. Abstract requests

public abstract class Request {
  /**
   * @returnPublic abstract int getRequestLevel(); }Copy the code

4. Specific request

public class RequestA extends Request {
  @Override
  public int getRequestLevel() {
    return10; }}Copy the code

5, use

public class HandlerTest { public static void main(String[] args) { RequestA request = new RequestA(); HandlerB = new handlerB (); HandlerA = new handlerA (handlerB); // Finally pass to HandlerB to handle handlera.handlerequest (request); }}Copy the code

OkHttp Interceptor

The pure chain of responsibility pattern is that if the handler processes, the request ends. OkHttp’s interceptor is in an impeccable chain of responsibility mode, where when a request arrives, the interceptor does some processing (adding parameters, etc.) and then passes it on to the next interceptor for processing.

1. Request interception processing

During a request, the request is processed through an interceptor

Response response = getResponseWithInterceptorChain();
Copy the code
The Response getResponseWithInterceptorChain () throws IOException {/ / to create a list of interceptors 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)); // Create RealInterceptorChain, Interceptor.Chain Chain = new RealInterceptorChain(interceptors, null, NULL, null, 0, originalRequest, this, eventListener, client.connectTimeoutMillis(), client.readTimeoutMillis(), client.writeTimeoutMillis());return chain.proceed(originalRequest);
}
Copy the code

Create the first RealInterceptorChain object, pass in a collection of interceptors, and proceed to handle the request.

2. Request processing

public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec, RealConnection connection) throws IOException { ...... // Create the next RealInterceptorChain, Next = new RealInterceptorChain(Interceptors, streamAllocation, httpCodec, connection, index + 1, request, call, eventListener, connectTimeout,readTimeout, writeTimeout); // Interceptor Interceptor = interceptors.get(index); Response Response = interceptor.intercept(next); .return response;
}
Copy the code
  • Create the next RealInterceptorChain object, pass in the variables in the current RealInterceptorChain as parameters, and pass in the index index+1.
  • Gets the interceptor at the current index position. When first created, the index is passed in as 0, indicating that the first interceptor is obtained. Then index+1 is passed in to obtain the next interceptor.
  • When passing in the next RealInterceptorChain to an Interceptor intercept, the method proceed of the next RealInterceptorChain is called internally

3. Interceptor interface

Public interface Interceptor {/** * intercepts the Chain and triggers the call of the next Interceptor * @param Chain object * @return* @throws IOException */ Response intercept(Chain chain) throws IOException; Interface Chain {// Return Request Request (); // Process the Request. Response proceed(Request Request) throws IOException; . }}Copy the code

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 = realchain.request (); StreamAllocation streamAllocation = realChain.streamAllocation(); // We need the network to satisfy this request. Possiblyfor validating a conditional GET.
    boolean doExtensiveHealthChecks = ! request.method().equals("GET");
    HttpCodec httpCodec = streamAllocation.newStream(client, chain, doExtensiveHealthChecks); RealConnection connection = streamAllocation.connection(); // Proceed of the next interceptor chain is called for processingreturnrealChain.proceed(request, streamAllocation, httpCodec, connection); }}Copy the code

As a concrete handler, the ConnectInterceptor receives the next RealInterceptorChain object and handles the request using the RealInterceptorChain’s proceed method. The whole chain call process is as follows: First Chain Procced — first Interceptor Interceptor — next Chain procced– next Interceptor Interceptor — next Chain Procced — the next Interceptor Interceptor….