1 概述
AOP 编程。每次的 proceed 是执行点,可以在执行点的前面和后面添加需要的业务逻辑。比如打打日志,失败重试,添加缓存等等。
拦截器就是基于责任链模式,每个节点有自己的职责,同时可以选择是否把任务传递给下一个环节拦截器的设计,可以像工厂流水线一样,传递用户发起的请求 Request,每一个拦截器完成相应的功能,从失败重试和重定向实现、请求头的修改和Cookie 的处理,缓存的处理,建立 TCP 和 SSH 连接,发送 Request 和读取 Response,每一个环节由专门的 Interceptor 负责。
2 类和接口
2.1 Inteceptor
主要方法
Intercept
。会传递一个 Chain 对象过来,可以在 Chain 在执行proceed
的前后添加代码。2.2 Chain
主要方法
proceed
。OkHttp 的唯一实现类是 RealInterceptorChain。内部维护了所有要执行的拦截器列表,在proceed
内部会唤醒下一个 Interceptor ,调用intercept
来进行下一步:public Response proceed(Request request, StreamAllocation streamAllocation, HttpStream httpStream, Connection connection) throws IOException { ... RealInterceptorChain next = new RealInterceptorChain( interceptors, streamAllocation, httpStream, connection, index + 1, request); Interceptor interceptor = interceptors.get(index); Response response = interceptor.intercept(next); ... return response; }
该类的主要成员有:
- List<Interceptor>
所有拦截器列表;
- StreamAllocation
用来协调 Connection,Stream 和 Calls 的关系。封装了网络连接创建的一些策略。比如使用 RouteSelector 和 RouteDatabase 在建联失败后的多 IP 路由的选择;HttpStream 流的创建;Connection 的创建和使用 ConnectionPool 进行连接复用等;
- HttpStream
网络数据流的抽象,因为不同的 HTTP 协议,流的传输方式不一样,有两个实现 Http1xStream 和 Http2xStream。主要的职责为写入 Request 请求,并且读取 Response 响应;
- Connection
网络连接的抽象,唯一实现 RealConnection。主要用来管理连接用的 Socket。RealConnection 调用
connect
来进行Socket 连接;- Request
请求体的抽象,包括方法、请求头、请求体;
RealInterceptorChain 对
proceed
进行了扩展,在拦截器链式传递的过程中增加了这些对象的传递。所以执行拦截器的时候,启动下一个拦截器的前,可以对这些对象进行创建或者修改,然后再传递给下一个拦截器,或者调用这些对象完成相应的功能。比如在 RetryAndFollowUpInterceptor 会创建 StreamAllocation,在 BridgeInterceptor 会修改 Request 的请求头,在 ConnectInterceptor 会调用 StreamAllocation 的newStream
方法建立连接等等。3 基本流程
Call 抽象了一次请求,唯一实现类为 RealCall,当我们调用
call.execute
发起请求后,整个请求的流程发生在下面的方法中:private Response getResponseWithInterceptorChain() throws IOException { // Build a full stack 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 (!retryAndFollowUpInterceptor.isForWebSocket()) { interceptors.addAll(client.networkInterceptors()); } interceptors.add(new CallServerInterceptor( retryAndFollowUpInterceptor.isForWebSocket())); Interceptor.Chain chain = new RealInterceptorChain( interceptors, null, null, null, 0, originalRequest); return chain.proceed(originalRequest); }
通过一系列拦截器进行链式操作,一环接一环,每个拦截器负责单独的任务,环环相扣完成整个请求:
- RetryAndFollowUpInterceptor
用来实现连接失败的重试和重定向;
- BridgeInterceptor
用来修改请求和响应的 header 信息;
- CacheInterceptor
用来实现响应缓存。比如获取到的 Response 带有 Date,Expires,Last-Modified,Etag 等 header,表示该 Response 可以缓存一定的时间,下次请求就可以不需要发往服务端,直接拿缓存的;
- ConnectInterceptor
用来打开到服务端的连接。其实是调用了 StreamAllocation 的
newStream
方法来打开连接的。建联的 TCP 握手,TLS 握手都发生该阶段。过了这个阶段,和服务端的 socket 连接打通;- CallServerInterceptor
用来发起请求并且得到响应。上一个阶段已经握手成功,HttpStream 流已经打开,所以这个阶段把 Request 的请求信息传入流中,并且从流中读取数据封装成 Response 返回;
OkHttp的拦截器机制分析
最新推荐文章于 2021-07-15 21:42:28 发布