2. Android 第三方框架 okhttp责任链模式的源码分析 深度解读二

摘要:OKHttp 的责任链模式是其核心设计,用于处理网络请求和响应。它通过将多个 Interceptor 对象串联成一个有序链条(Chain)来实现。每个拦截器负责特定任务(如重试、缓存、连接、日志、修改请求/响应等)。请求会按顺序依次经过每个拦截器处理,每个拦截器可以选择处理请求、调用下一个拦截器,或修改响应。这种设计实现了高度模块化、灵活性和可扩展性,开发者可以轻松添加、移除或修改处理逻辑。

1.OKHttp框架中用到了哪些设计模式

设计模式应用
模式 应用场景 代表类
责任链模式 拦截器链处理请求/响应 Interceptor.Chain
建造者模式 构建复杂对象(Request/OkHttpClient) Request.Builder
工厂模式 创建连接对象 ConnectionPool
观察者模式 WebSocket 事件回调 WebSocketListener
策略模式 缓存策略选择 CacheStrategy
门面模式 简化复杂HTTP操作接口 OkHttpClient

2.设计模式之责任链模式

11. Android 设计模式 核心四之责任链模式 在大型企业级APP的落地责任链模式是一种行为设计模式,允 - 掘金)

3.责任链模式的源码

核心源码解析

3.1. 拦截器接口定义
java 复制代码
public interface Interceptor {
    // 核心方法:处理请求/响应
    Response intercept(Chain chain) throws IOException;

    interface Chain {
        // 获取当前请求
        Request request();
        
        // 关键:将请求传递给链中的下一个拦截器
        Response proceed(Request request) throws IOException;
    }
}
3.2. 责任链实现(RealInterceptorChain)

链式调用原理

OkHttp通过RealInterceptorChain类实现责任链的核心逻辑:

java 复制代码
public class RealInterceptorChain implements Interceptor.Chain {
    private final List<Interceptor> interceptors;
    private final int index; // 当前拦截器索引
    private final Request request;
    
    public Response proceed(Request request) throws IOException {
        // 1. 检查是否还有下一个拦截器
        if (index >= interceptors.size()) throw new AssertionError();
        
        // 2. 创建下一个责任链(关键设计)
        RealInterceptorChain next = new RealInterceptorChain(
            interceptors, index + 1, request, ...);
        
        // 3. 获取当前拦截器
        Interceptor interceptor = interceptors.get(index);
        
        // 4. 调用当前拦截器并传入新链
        Response response = interceptor.intercept(next);
        
        return response;
    }
}
3.3 拦截器链初始化(RealCall)

链的动态构建

拦截器链在RealCall中动态构建:

拦截器的组装

csharp 复制代码
Response getResponseWithInterceptorChain() throws IOException {
    // 构建完整拦截器链
    List<Interceptor> interceptors = new ArrayList<>();
    
    // 添加用户自定义拦截器
    interceptors.addAll(client.interceptors());
    
    // 添加内置拦截器
    interceptors.add(new RetryAndFollowUpInterceptor(client));
    interceptors.add(new BridgeInterceptor(client.cookieJar()));
    interceptors.add(new CacheInterceptor(client.internalCache()));
    interceptors.add(new ConnectInterceptor(client));
    
    // 添加网络拦截器
    interceptors.addAll(client.networkInterceptors());
    
    // 添加最终网络I/O拦截器
    interceptors.add(new CallServerInterceptor(forWebSocket));
    
    // 创建责任链
    Interceptor.Chain chain = new RealInterceptorChain(
        interceptors, null, null, null, 0, originalRequest);
    
    // 启动责任链处理
    return chain.proceed(originalRequest);
}
3.4. 典型拦截器实现(BridgeInterceptor)
java 复制代码
public Response intercept(Chain chain) throws IOException {
    // 1. 请求前处理:添加头信息
    Request userRequest = chain.request();
    Request.Builder requestBuilder = userRequest.newBuilder();
    
    // 添加必要头(Host, Connection, User-Agent等)
    // ...
    
    // 2. 传递给下一个拦截器
    Response networkResponse = chain.proceed(requestBuilder.build());
    
    // 3. 响应后处理:解压Gzip等
    Response.Builder responseBuilder = networkResponse.newBuilder()
        .request(userRequest);
    
    if (transparentGzip && "gzip".equalsIgnoreCase(networkResponse.header("Content-Encoding"))) {
        // Gzip解压处理
    }
    
    return responseBuilder.build();
}

3.5. 双向处理流程

每个拦截器的处理分为两个阶段

3.6 责任链是如何实现依次请求,但是响应反着来的

OkHttp 责任链模式通过递归调用和栈结构实现了请求顺序执行,响应逆序返回的精妙机制。这种设计类似于函数调用栈的工作原理:

递归终止

scss 复制代码
// RealInterceptorChain.proceed()
if (index >= interceptors.size()) throw new AssertionError();

// CallServerInterceptor中
public Response intercept(Chain chain) {
    // 不再调用chain.proceed()
    Response response = doNetworkIO();
    return response;
}

完整请求生命周期

4. okhttp责任链模式,设计优势分析

4.1. 开闭原则

  • 开放:可以轻松添加新拦截器而不修改现有代码
  • 封闭:拦截器实现不依赖其他拦截器

4.2. 单一职责

每个拦截器只关注特定功能:

  • RetryAndFollowUpInterceptor:重试和重定向
  • BridgeInterceptor:HTTP协议桥接
  • CacheInterceptor:缓存处理
  • ConnectInterceptor:连接管理
  • CallServerInterceptor:网络I/O

4.3.这种设计:

  • 保证链的不可变性
  • 支持递归调用
  • 允许拦截器修改后续链

项目的地址:github.com/pengcaihua1...

相关推荐
天蓝色的鱼鱼7 分钟前
从零实现浏览器摄像头控制与视频录制:基于原生 JavaScript 的完整指南
前端·javascript
三原29 分钟前
7000块帮朋友做了2个小程序加一个后台管理系统,值不值?
前端·vue.js·微信小程序
popoxf38 分钟前
在新版本的微信开发者工具中使用npm包
前端·npm·node.js
爱编程的喵1 小时前
React Router Dom 初步:从传统路由到现代前端导航
前端·react.js
每天吃饭的羊1 小时前
react中为啥使用剪头函数
前端·javascript·react.js
Nicholas682 小时前
Flutter帧定义与60-120FPS机制
前端
多啦C梦a2 小时前
【适合小白篇】什么是 SPA?前端路由到底在路由个啥?我来给你聊透!
前端·javascript·架构
薛定谔的算法2 小时前
《长安的荔枝·事件流版》——一颗荔枝引发的“冒泡惨案”
前端·javascript·编程语言
中微子2 小时前
CSS 的 position 你真的理解了吗?
前端·css
谜构2 小时前
【0编码】我使用Trae AI开发了一个【随手记账单格式化工具】
前端