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...

相关推荐
张风捷特烈40 分钟前
匠心千游 | 纯 AI 打造休闲小游戏
前端·微信小程序·游戏开发
longze_75 小时前
Vue中:deep()和 ::v-deep选择器的区别
前端·javascript·vue.js
太阳伞下的阿呆8 小时前
本地环境vue与springboot联调
前端·vue.js·spring boot
阳光是sunny8 小时前
走进微前端(1)手写single-spa核心原理
前端·javascript·vue.js
烛阴9 小时前
Ceil -- 从平滑到阶梯
前端·webgl
90后的晨仔9 小时前
🔍Vue 模板引用(Template Refs)全解析:当你必须操作 DOM 时
前端·vue.js
90后的晨仔9 小时前
👂 Vue 侦听器(watch)详解:监听数据的变化
前端·vue.js
90后的晨仔9 小时前
深入浅出 Vue 的 computed:不仅仅是“计算属性”那么简单!
前端·vue.js
Nan_Shu_61410 小时前
学习:入门uniapp Vue3组合式API版本(17)
前端·vue.js·学习·uni-app
止观止10 小时前
Remix框架:高性能React全栈开发实战
前端·react.js·前端框架·remix