okhttp5.x 需要在 请求级别 控制是否使用重试拦截器,而不是在客户端级别

方案1:使用不同的 HttpClient(推荐)

创建两个不同的 HttpClient 实例:

java
public static final OkHttpClient httpClient;          // 普通客户端(无重试)
public static final OkHttpClient httpClientWithRetry; // 带重试的客户端

static {
    try {
        executorService = createThreadPool();
        
        // 创建两个客户端实例
        httpClient = createHttpClient(false, null);                    // 无重试
        httpClientWithRetry = createHttpClient(false, HttpUtils.retryInterceptor(2, 100L, true)); // 有重试
        
        registerShutdownHook();
    } catch (Exception e) {
        throw new ExceptionInInitializerError(e);
    }
}

// sendRequestOkhttp 使用带重试的客户端
public static String sendRequestOkhttp(String url, String referer, boolean useAgent, String cookies) throws Exception {
    // ... 其他代码不变 ...
    
    // 使用带重试的客户端
    try (Response response = httpClientWithRetry.newCall(request).execute()) {
        // ... 处理响应 ...
    }
}

// sendRequestDataYes 使用普通客户端
public static String sendRequestDataYes(String url, String referer, boolean useAgent, String cookies) throws Exception {
    // ... 其他代码不变 ...
    
    // 使用普通客户端(无重试)
    try (Response response = httpClient.newCall(request).execute()) {
        // ... 处理响应 ...
    }
}

方案2:使用自定义拦截器(动态控制)

创建智能拦截器,根据请求特征决定是否重试:

java
public static final OkHttpClient httpClient;

static {
    try {
        executorService = createThreadPool();
        
        // 创建智能重试拦截器
        Interceptor smartRetryInterceptor = createSmartRetryInterceptor();
        httpClient = createHttpClient(false, smartRetryInterceptor);
        
        registerShutdownHook();
    } catch (Exception e) {
        throw new ExceptionInInitializerError(e);
    }
}

/**
 * 智能重试拦截器:根据请求特征决定是否重试
 */
private static Interceptor createSmartRetryInterceptor() {
    return chain -> {
        Request originalRequest = chain.request();
        
        // 判断是否为 DataYes 请求(根据 URL 或其他特征)
        boolean isDataYesRequest = originalRequest.url().toString().contains("datayes") || 
                                  originalRequest.header("Authorization") != null;
        
        // 如果是 DataYes 请求,不重试
        if (isDataYesRequest) {
            return chain.proceed(originalRequest);
        }
        
        // 其他请求使用重试逻辑
        return HttpUtils.retryInterceptor(2, 100L, true).intercept(chain);
    };
}

方案3:使用请求标记(最灵活)

通过请求标签来控制重试行为:

java
public static final OkHttpClient httpClient;

static {
    try {
        executorService = createThreadPool();
        
        // 创建条件重试拦截器
        Interceptor conditionalRetryInterceptor = createConditionalRetryInterceptor();
        httpClient = createHttpClient(false, conditionalRetryInterceptor);
        
        registerShutdownHook();
    } catch (Exception e) {
        throw new ExceptionInInitializerError(e);
    }
}

/**
 * 条件重试拦截器
 */
private static Interceptor createConditionalRetryInterceptor() {
    return chain -> {
        Request originalRequest = chain.request();
        
        // 检查请求标签
        Boolean enableRetry = originalRequest.tag(Boolean.class);
        if (enableRetry != null && !enableRetry) {
            // 明确禁用重试,直接执行
            return chain.proceed(originalRequest);
        }
        
        // 默认启用重试
        return HttpUtils.retryInterceptor(2, 100L, true).intercept(chain);
    };
}

// sendRequestOkhttp - 启用重试(默认)
public static String sendRequestOkhttp(String url, String referer, boolean useAgent, String cookies) throws Exception {
    // ... 构建请求 ...
    Request request = requestBuilder.build(); // 不设置标签,使用默认重试
    try (Response response = httpClient.newCall(request).execute()) {
        // ... 处理响应 ...
    }
}

// sendRequestDataYes - 禁用重试
public static String sendRequestDataYes(String url, String referer, boolean useAgent, String cookies) throws Exception {
    // ... 构建请求 ...
    
    // 添加标签禁用重试
    Request request = requestBuilder
        .tag(Boolean.class, false)  // 明确禁用重试
        .build();
        
    try (Response response = httpClient.newCall(request).execute()) {
        // ... 处理响应 ...
    }
}

方案4:使用不同的拦截器配置

java
public static final OkHttpClient httpClient;
private static final Interceptor retryInterceptor = HttpUtils.retryInterceptor(2, 100L, true);

static {
    try {
        executorService = createThreadPool();
        httpClient = createHttpClient(false, null); // 不添加全局重试拦截器
        registerShutdownHook();
    } catch (Exception e) {
        throw new ExceptionInInitializerError(e);
    }
}

// 为特定请求手动添加重试
public static String sendRequestOkhttp(String url, String referer, boolean useAgent, String cookies) throws Exception {
    // ... 构建请求 ...
    
    // 为这个请求创建临时客户端(带重试)
    OkHttpClient clientWithRetry = httpClient.newBuilder()
        .addInterceptor(retryInterceptor)
        .build();
        
    try (Response response = clientWithRetry.newCall(request).execute()) {
        // ... 处理响应 ...
    }
}

// sendRequestDataYes 使用原始客户端(无重试)
public static String sendRequestDataYes(String url, String referer, boolean useAgent, String cookies) throws Exception {
    // ... 构建请求 ...
    try (Response response = httpClient.newCall(request).execute()) {
        // ... 处理响应 ...
    }
}

推荐使用方案1

方案1 是最简单清晰的:

  • 代码意图明确

  • 性能最佳(无需运行时判断)

  • 易于维护和调试

  • 符合单一职责原则

选择哪种方案取决于你的具体需求:

  • 如果两种请求模式固定,用方案1

  • 如果需要动态控制,用方案3

  • 如果根据URL特征区分,用方案2

posted @ 2025-11-13 10:24  锐洋智能  阅读(12)  评论(0)    收藏  举报