OkHttp3.X 工具类封装:链式调用,支持HTTPS、重试、文件上传【内含常用设计模式设计示例】

OkHttp3.X 工具类封装:链式调用,支持HTTPS、重试、文件上传

基于OkHttp3.X封装,提供链式调用API,简化GET/POST请求,支持HTTPS、自动重试、文件上传等功能,提升开发效率。


在 Android 和 Java 开发中,OkHttp 是最常用的网络请求库之一。为了简化日常开发中的重复配置,提升开发效率,本文将分享一个线程安全、支持默认与自定义配置、链式调用的 OkHttp 工具类,并详细解析其核心功能与实现细节。

一、工具类核心优势

  1. 双重配置模式
    • 默认配置:预定义通用参数(超时时间、连接池、重试策略),适用于大多数场景。
    • 自定义配置:基于默认配置扩展,支持添加拦截器、修改超时参数、配置 HTTPS 证书等。
  2. 线程安全
    • 使用双重检查锁定实现单例,确保多线程环境下实例唯一。
  3. 链式请求构建
    • 支持 GET/POST 请求,灵活拼接 URL 参数、请求头、请求体(FormData、JSON、二进制等)。
  4. HTTPS 安全适配
    • 支持调试模式(跳过证书验证)、自定义证书(自签名证书)、系统默认证书三种模式。
  5. 统一异常处理
    • 自动关闭响应体,封装非 2xx 状态码为 HttpException,简化错误处理逻辑。

二、快速开始

1. 引入依赖

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.12.0</version>
</dependency>

2. 工具类核心功能

2.1 GET请求
// 带URL参数和Headers
String result = OkHttp_Util.get("https://api.example.com")
    .addUrlParam("page", "1")
    .addHeader("Authorization", "Bearer token123")
    .execute_Pro();

// 批量添加参数
Map<String, String> params = new HashMap<>();
params.put("key1", "value1");
params.put("key2", "value2");
String result = OkHttp_Util.get("https://api.example.com")
    .addUrlParam(params)
    .execute_Pro();
2.2 POST请求
// 提交JSON
String json = "{\"name\":\"Dolphin\",\"age\":25}";
String result = OkHttp_Util.post("https://api.example.com")
    .jsonBody(json)
    .execute_Pro();

// FormData表单
Map<String, String> formData = new HashMap<>();
formData.put("username", "admin");
formData.put("password", "123456");
String result = OkHttp_Util.post("https://api.example.com")
    .formData(formData)
    .execute_Pro();

// 文件上传
File file = new File("avatar.jpg");
MediaType mediaType = MediaType.parse("image/jpeg");
String result = OkHttp_Util.post("https://api.upload.com")
    .formData("file", file, mediaType)
    .execute_Pro();
2.3 自定义配置
// 创建自定义Client(添加拦截器+长超时)
OkHttpClient.Builder builder = OkHttp_Util.customBuilder()
    .addInterceptor(new OkHttp_Util.LoggingInterceptor())
    .connectTimeout(30, TimeUnit.SECONDS);

OkHttp_Util.buildCustomInstance(builder);
OkHttpClient customClient = OkHttp_Util.getCustomInstance();

// 使用自定义Client发起请求
String result = OkHttp_Util.get("https://api.example.com", customClient)
    .addUrlParam("debug", "true")
    .execute_Pro();
2.4 异步请求
OkHttp_Util.get("https://api.example.com")
    .enqueue(new Callback() {
        @Override
        public void onResponse(Call call, Response response) throws IOException {
            String body = OkHttp_Util.parseResponse(response);
            // 处理响应
        }

        @Override
        public void onFailure(Call call, IOException e) {
            // 处理失败
        }
    });

三、核心设计解析

3.1 单例模式管理

// 默认配置单例
private static volatile OkHttpClient defaultInstance;

// 自定义配置单例
private static volatile OkHttpClient customInstance;

public static OkHttpClient getDefaultInstance() {
    if (defaultInstance == null) {
        synchronized (OkHttp_Util.class) {
            if (defaultInstance == null) {
                defaultInstance = defaultBuilder().build();
            }
        }
    }
    return defaultInstance;
}

3.2 HTTPS安全配置

支持三种模式:

  • 调试模式:跳过证书验证(仅测试环境)
  • 自定义证书:指定PEM证书
  • 系统默认:使用系统CA证书
private static OkHttpClient.Builder configSSL(OkHttpClient.Builder builder, OkHttpConfig config) {
    // 调试模式:信任所有证书
    if (config.debugMode) {
        builder.sslSocketFactory(createInsecureSocketFactory(), new TrustAllManager());
    }
    // 自定义证书
    else if (config.trustedCertificates != null) {
        X509TrustManager trustManager = createCustomTrustManager(config.trustedCertificates);
        builder.sslSocketFactory(trustManager.getSocketFactory(), trustManager);
    }
    // 系统默认证书
    else {
        X509TrustManager trustManager = getSystemTrustManager();
        builder.sslSocketFactory(trustManager.getSocketFactory(), trustManager);
    }
    return builder;
}

3.3 重试拦截器

private static class RetryInterceptor implements Interceptor {
    private final int maxRetries;

    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        IOException exception = null;

        for (int i = 0; i <= maxRetries; i++) {
            try {
                Response response = chain.proceed(request);
                if (response.isSuccessful()) return response;
            } catch (IOException e) {
                exception = e;
            }
        }
        throw exception != null ? exception : new IOException("请求失败");
    }
}

四、注意事项

  1. HTTPS安全:生产环境务必使用系统证书或自定义证书
  2. 资源释放:同步请求自动关闭响应体,异步需手动关闭
  3. 超时配置:根据业务需求调整默认超时时间
  4. 线程安全:OkHttpClient实例线程安全,建议复用
  5. 异常处理:使用execute_Pro()自动处理非200响应

五、完整代码

package com.dolphin.util;

import okhttp3.*;

import javax.net.ssl.*;
import java.io.File;
import java.io.IOException;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * OkHttp 工具类(线程安全)
 * <p>
 * 提供两种 OkHttpClient 实例管理模式:
 * <ul>
 *     <li>【默认配置】预定义通用网络参数,适用于大多数场景:
 *         <ul>
 *             <li>连接/读取/写入超时:10 秒</li>
 *             <li>允许重定向和失败重试(最大 3 次)</li>
 *             <li>连接池:5 个空闲连接,保持 10 分钟</li>
 *             <li>系统默认证书信任策略(非调试模式)</li>
 *         </ul>
 *     </li>
 *     <li>【自定义配置】基于默认配置扩展,支持灵活定制:
 *         <ul>
 *             <li>添加拦截器(日志、签名、认证等)</li>
 *             <li>修改超时参数、连接池配置</li>
 *             <li>配置 HTTPS 证书信任策略(调试模式/自定义证书/系统默认)</li>
 *         </ul>
 *     </li>
 * </ul>
 * <p>
 * 使用示例:
 * <pre>
 * // 1. 使用默认配置发起 GET 请求
 * String resultDefault = OkHttp_Util.get("https://api.example.com")
 *     .addUrlParam("page", "1")
 *     .addHeader("User-Agent", "OkHttp-Util/1.0")
 *     .execute_Pro(); // 自动处理响应和异常
 *
 * // 2. 自定义配置(添加日志拦截器+长连接超时)
 * OkHttpClient.Builder customBuilder = OkHttp_Util.customBuilder()
 *     .addInterceptor(new OkHttp_Util.LoggingInterceptor()) // 添加自定义拦截器
 *     .connectTimeout(60, TimeUnit.SECONDS); // 延长连接超时时间
 * OkHttp_Util.buildCustomInstance(customBuilder); // 初始化自定义单例
 * OkHttpClient customClient = OkHttp_Util.getCustomInstance(); // 获取到 一个 单例,并且是自定义配置的 OkHttpClient 实例
 * String resultCustom = OkHttp_Util.get("https://api.example.com", customClient)
 *     .addUrlParam("page", "1")
 *     .addHeader("User-Agent", "OkHttp-Util/1.0")
 *     .execute_Pro(); // 自动处理响应和异常
 *
 * // 3. 上传文件(multipart/form-data)
 * File file = new File("example.pdf");
 * String uploadResult = OkHttp_Util.post("https://api.upload.com")
 *     .addHeader("Authorization", "Bearer YOUR_TOKEN")
 *     .formData("file", file, MediaType.parse("application/pdf")) // 上传文件
 *     .execute_Pro();
 *
 * // 4. 处理异步请求
 * OkHttp_Util.get("https://api.async.com")
 *     .enqueue(new Callback() {
 *         @Override
 *         public void onResponse(Call call, Response response) throws IOException {
 *             String body = OkHttp_Util.parseResponse(response);
 *             // 处理成功响应
 *         }
 *         @Override
 *         public void onFailure(Call call, IOException e) {
 *             // 处理失败(网络异常)
 *         }
 *     });
 * </pre>
 *
 * @author DolphinHome
 * @date 2025/04/30
 */
public class OkHttp_Util {
    /*
// 使用 Log4j 记录日志
private static final Logger log = LoggerFactory.getLogger(OkHttp_Util.class);
     */

    // ------------------------------ 单例实例 ------------------------------
    /**
     * 默认配置的 OkHttpClient 单例(线程安全,双重检查锁定实现)
     */
    private static volatile OkHttpClient defaultInstance;
    /**
     * 自定义配置的 OkHttpClient 单例(线程安全,按需初始化)
     */
    private static volatile OkHttpClient customInstance;

    // ------------------------------ 构造方法 ------------------------------

    /**
     * 私有构造方法,禁止类实例化
     * <p>
     * 通过断言错误防止反射创建实例,强化工具类设计
     * </p>
     *
     * @throws AssertionError 始终抛出,明确禁止实例化
     */
    private OkHttp_Util() {
        throw new AssertionError("不可实例化工具类");
    }

    // ------------------------------ 配置类 ------------------------------

    /**
     * OkHttp 配置参数容器
     * <p>
     * 包含网络请求核心配置,所有参数均有默认值:
     * <ul>
     *     <li>超时:连接/读取/写入默认 10 秒</li>
     *     <li>重定向:默认允许</li>
     *     <li>重试:默认允许,最大 3 次</li>
     *     <li>连接池:5 个空闲连接,保持 10 分钟</li>
     *     <li>HTTPS:默认使用系统证书,调试模式可跳过验证</li>
     * </ul>
     *
     * <p>
     *  自定义证书信任(生产环境):
     * <pre>
     * // 1. 加载 PEM 证书文件
     * X509Certificate cert = loadCertificateFromFile("trusted.crt");
     * OkHttpConfig config = new OkHttpConfig();
     * config.setTrustedCertificates(new X509Certificate[]{cert}); // 设置自定义证书
     *
     * // 2. 通过自定义构建器应用配置(需修改 defaultBuilder 逻辑,此处仅示例)
     * OkHttpClient.Builder builder = OkHttp_Util.customBuilder();
     * configSSL(builder, config); // 内部方法,实际通过 OkHttpConfig 传递
     * </pre>
     * <p>
     *  调试模式(测试环境):
     * <pre>
     * OkHttpConfig debugConfig = new OkHttpConfig();
     * debugConfig.setDebugMode(true); // 跳过所有证书验证(危险!仅测试用)
     * </pre>
     */
    public static class OkHttpConfig {
        // 超时配置(单位:秒)
        private int connectTimeout; // 连接超时:建立 TCP 连接的最大等待时间
        private int readTimeout;    // 读取超时:等待服务器响应数据的最大时间
        private int writeTimeout;   // 写入超时:发送请求体到服务器的最大时间


        // 重定向策略
        private boolean followRedirects; // 是否允许自动跟随重定向(默认允许)

        // 重试策略
        private boolean retryOnConnectionFailure; // 连接失败时是否重试(默认允许)
        private int maxRetryCount;                // 最大重试次数(默认 3 次)


        // 连接池配置
        private int maxIdleConnections = 5;  // 最大空闲连接数(默认 5 个)
        private long keepAliveDuration = 10; // 连接存活时间(默认 10 分钟)
        private TimeUnit keepAliveUnit = TimeUnit.MINUTES; // 存活时间单位


        // HTTPS 安全配置
        private boolean debugMode;         // 调试模式(跳过证书验证,默认关闭)
        private X509Certificate[] trustedCertificates; // 自定义信任证书(PEM 格式,默认 null)

        /**
         * 无参构造:使用全默认配置
         */
        public OkHttpConfig() {
            this(
                    10,
                    10,
                    10,
                    true,
                    true,
                    3,
                    5,
                    10,
                    TimeUnit.MINUTES,
                    false,
                    null
            );
        }

        public OkHttpConfig(
                int connectTimeout,
                int readTimeout,
                int writeTimeout,
                boolean followRedirects,
                boolean retryOnConnectionFailure,
                int maxRetryCount,
                int maxIdleConnections,
                int keepAliveDuration,
                TimeUnit keepAliveUnit,
                boolean debugMode,
                X509Certificate[] trustedCertificates
        ) {
            this.connectTimeout = connectTimeout;
            this.readTimeout = readTimeout;
            this.writeTimeout = writeTimeout;
            this.followRedirects = followRedirects;
            this.retryOnConnectionFailure = retryOnConnectionFailure;
            this.maxRetryCount = maxRetryCount;
            this.maxIdleConnections = maxIdleConnections;
            this.keepAliveDuration = keepAliveDuration;
            this.keepAliveUnit = keepAliveUnit;
            this.debugMode = debugMode;
            this.trustedCertificates = trustedCertificates;
        }

        // region get/set 方法

        public int getConnectTimeout() {
            return connectTimeout;
        }

        public void setConnectTimeout(int connectTimeout) {
            this.connectTimeout = connectTimeout;
        }

        public int getReadTimeout() {
            return readTimeout;
        }

        public void setReadTimeout(int readTimeout) {
            this.readTimeout = readTimeout;
        }

        public int getWriteTimeout() {
            return writeTimeout;
        }

        public void setWriteTimeout(int writeTimeout) {
            this.writeTimeout = writeTimeout;
        }

        public boolean isFollowRedirects() {
            return followRedirects;
        }

        public void setFollowRedirects(boolean followRedirects) {
            this.followRedirects = followRedirects;
        }

        public boolean isRetryOnConnectionFailure() {
            return retryOnConnectionFailure;
        }

        public void setRetryOnConnectionFailure(boolean retryOnConnectionFailure) {
            this.retryOnConnectionFailure = retryOnConnectionFailure;
        }

        public int getMaxRetryCount() {
            return maxRetryCount;
        }

        public void setMaxRetryCount(int maxRetryCount) {
            this.maxRetryCount = maxRetryCount;
        }

        public int getMaxIdleConnections() {
            return maxIdleConnections;
        }

        public void setMaxIdleConnections(int maxIdleConnections) {
            this.maxIdleConnections = maxIdleConnections;
        }

        public long getKeepAliveDuration() {
            return keepAliveDuration;
        }

        public void setKeepAliveDuration(long keepAliveDuration) {
            this.keepAliveDuration = keepAliveDuration;
        }

        public TimeUnit getKeepAliveUnit() {
            return keepAliveUnit;
        }

        public void setKeepAliveUnit(TimeUnit keepAliveUnit) {
            this.keepAliveUnit = keepAliveUnit;
        }

        public boolean isDebugMode() {
            return debugMode;
        }

        public void setDebugMode(boolean debugMode) {
            this.debugMode = debugMode;
        }

        public X509Certificate[] getTrustedCertificates() {
            return trustedCertificates;
        }

        public void setTrustedCertificates(X509Certificate[] trustedCertificates) {
            this.trustedCertificates = trustedCertificates;
        }

        // endregion
    }

    // ------------------------------ 自定义配置单例 ------------------------------

    /**
     * 获取自定义配置的 OkHttpClient 单例
     * <p>
     * 必须先通过 {@link #buildCustomInstance(OkHttpClient.Builder)} 初始化
     * </p>
     * <p>
     * 使用示例:
     * </p>
     * <pre>
     * OkHttpClient.Builder customBuilder = OkHttp_Util.customBuilder()
     *     .addInterceptor(new OkHttp_Util.LoggingInterceptor()) // 添加自定义拦截器
     *     .connectTimeout(60, TimeUnit.SECONDS); // 延长连接超时时间
     * OkHttp_Util.buildCustomInstance(customBuilder); // 初始化自定义单例
     * OkHttpClient customClient = OkHttp_Util.getCustomInstance(); // 获取到 一个 单例,并且是自定义配置的 OkHttpClient 实例
     * String resultCustom = OkHttp_Util.get("https://api.example.com", customClient)
     *     .addUrlParam("page", "1")
     *     .addHeader("User-Agent", "OkHttp-Util/1.0")
     *     .execute_Pro(); // 自动处理响应和异常
     * </pre>
     *
     * @return 自定义配置的 OkHttpClient 实例(线程安全单例)
     * @throws IllegalStateException 未初始化自定义配置时抛出
     */
    public static OkHttpClient getCustomInstance() {
        if (customInstance == null) {
            throw new IllegalStateException("自定义 OkHttpClient 未初始化,请先调用 buildCustomInstance()");
        }
        return customInstance;
    }

    /**
     * 初始化自定义配置单例
     * <p>
     * 基于默认配置构建器扩展,支持添加拦截器、修改超时等
     * <p>
     * <b>线程安全</b>:采用双重检查锁定,确保单例唯一性
     * </p>
     * <p>
     * 使用示例:
     * </p>
     * <pre>
     * OkHttpClient.Builder customBuilder = OkHttp_Util.customBuilder()
     *     .addInterceptor(new OkHttp_Util.LoggingInterceptor()) // 添加自定义拦截器
     *     .connectTimeout(60, TimeUnit.SECONDS); // 延长连接超时时间
     * OkHttp_Util.buildCustomInstance(customBuilder); // 初始化自定义单例
     * OkHttpClient customClient = OkHttp_Util.getCustomInstance(); // 获取到 一个 单例,并且是自定义配置的 OkHttpClient 实例
     * String resultCustom = OkHttp_Util.get("https://api.example.com", customClient)
     *     .addUrlParam("page", "1")
     *     .addHeader("User-Agent", "OkHttp-Util/1.0")
     *     .execute_Pro(); // 自动处理响应和异常
     * </pre>
     *
     * @param builder OkHttpClient 构建器(不可为 null)
     * @throws NullPointerException builder 为 null 时抛出
     */
    public static void buildCustomInstance(OkHttpClient.Builder builder) {
        if (builder == null) throw new NullPointerException("builder 不能为 null");
        if (customInstance == null) {
            synchronized (OkHttp_Util.class) {
                if (customInstance == null) {
                    customInstance = builder.build();
                }
            }
        }
    }

    /**
     * 获取可扩展的 OkHttpClient 构建器(基于默认配置)
     * <p>
     * 每次调用返回新的构建器实例,不影响现有单例:
     * - 包含默认的超时时间、连接池和重试策略
     * - 支持添加自定义拦截器(如签名、认证、日志等)
     * - 可修改 HTTPS 证书信任策略
     * </p>
     * <p>
     * 使用示例:
     * </p>
     * <pre>
     * // 自定义配置 OkHttpClient 单例
     * OkHttpClient.Builder customBuilder = OkHttp_Util.customBuilder()
     *     .addInterceptor(new OkHttp_Util.LoggingInterceptor()) // 添加自定义拦截器
     *     .connectTimeout(60, TimeUnit.SECONDS); // 延长连接超时时间
     * OkHttp_Util.buildCustomInstance(customBuilder); // 初始化自定义单例
     * OkHttpClient customClient = OkHttp_Util.getCustomInstance(); // 获取到 一个 单例,并且是自定义配置的 OkHttpClient 实例【注意:此客户端是单例的,调用后会将其设置为单例实例】
     * String resultCustom = OkHttp_Util.get("https://api.example.com", customClient)
     *     .addUrlParam("page", "1")
     *     .addHeader("User-Agent", "OkHttp-Util/1.0")
     *     .execute_Pro(); // 自动处理响应和异常
     *
     *
     * // 另一个 OkHttpClient 实例(非单例)
     * OkHttpClient customClient = OkHttp_Util.customBuilder()
     *      .addInterceptor(new XXXXXInterceptor())
     *      .connectTimeout(60, TimeUnit.SECONDS)
     *      .build(); // 获取到了一个自定义配置的 OkHttpClient 实例【注意:此客户端不是单例的,每次调用都会创建一个新的客户端】
     * String resultCustom = OkHttp_Util.get("https://api.example.com", customClient)
     *     .addUrlParam("page", "1")
     *     .addHeader("User-Agent", "OkHttp-Util/1.0")
     *     .execute_Pro(); // 自动处理响应和异常
     * </pre>
     *
     * @return 预配置默认参数的 OkHttpClient.Builder 实例
     */
    public static OkHttpClient.Builder customBuilder() {
        // 通过newBuilder()方法克隆默认配置,保证原实例不受影响
        return getDefaultInstance().newBuilder();
    }

    // ------------------------------ 默认配置单例 ------------------------------

    /**
     * 获取默认配置的 OkHttpClient 单例
     * <p>
     * 首次调用时初始化,采用双重检查锁定保证线程安全
     * <p>
     * 默认配置详情:
     * <ul>
     *     <li>超时:10 秒(连接/读取/写入)</li>
     *     <li>连接池:5 个空闲连接,保持 10 分钟</li>
     *     <li>重试策略:3 次失败重试(通过 {@link RetryInterceptor} 实现)</li>
     *     <li>HTTPS:使用系统默认证书信任策略(非调试模式)</li>
     * </ul>
     * </p>
     * <p>
     * 使用示例:
     * </p>
     * <pre>
     * OkHttpClient client = OkHttp_Util.getDefaultInstance(); // 获取到 一个 单例,并且默认配置过的 OkHttpClient 实例
     * Request request = new Request.Builder()
     *     .url("https://api.default.com")
     *     .get()
     *     .build();
     * try (Response response = client.newCall(request).execute()) {
     *     String body = OkHttp_Util.parseResponse(response);
     * }
     * </pre>
     *
     * @return 预配置的 OkHttpClient 单例(线程安全)
     */
    public static OkHttpClient getDefaultInstance() {
        // 第一次检查:避免每次访问都进行同步
        if (defaultInstance == null) {
            synchronized (OkHttp_Util.class) {
                // 第二次检查:防止重复创建
                if (defaultInstance == null) {
                    defaultInstance = defaultBuilder().build(); // 使用默认的自定义配置
                }
            }
        }
        return defaultInstance;
    }

    /**
     * 创建默认配置的 OkHttpClient.Builder
     * <p>
     * 包含以下核心配置:
     * <ol>
     *     <li>基础超时参数(10 秒)</li>
     *     <li>连接池配置(5 个空闲连接,10 分钟存活)</li>
     *     <li>重试拦截器(最大 3 次重试)</li>
     *     <li>HTTPS 证书信任策略(根据 {@link OkHttpConfig} 动态配置)</li>
     * </ol>
     * </p>
     *
     * @return 预配置默认参数的构建器实例
     */
    private static OkHttpClient.Builder defaultBuilder() {

        // 自定义配置
        OkHttpConfig config = new OkHttpConfig();
        OkHttpClient.Builder builder = new OkHttpClient.Builder()
                // 设置连接超时(建立TCP连接的最大等待时间)
                .connectTimeout(config.connectTimeout, TimeUnit.SECONDS)
                // 设置读取超时(等待服务器返回数据的最大时间)
                .readTimeout(config.readTimeout, TimeUnit.SECONDS)
                // 设置写入超时(发送请求体到服务器的最大时间)
                .writeTimeout(config.writeTimeout, TimeUnit.SECONDS)
                // 设置是否允许重定向
                .followRedirects(config.followRedirects)
                // 设置是否允许失败重试
                .retryOnConnectionFailure(config.retryOnConnectionFailure)

                // 配置连接池(复用HTTP/HTTP2连接,减少延迟)
                .connectionPool(new ConnectionPool(
                        config.maxIdleConnections, // 最大空闲连接数
                        config.keepAliveDuration, // 保持连接时间
                        config.keepAliveUnit)) // 保持连接时间单位

                // TODO: 通过 Interceptor 实现 最大重试次数
                .addInterceptor(new RetryInterceptor(config.maxRetryCount));

        // 设置信任证书(PEM格式)【测试环境中 debug=true 时,不设置信任证书】
        configSSL(builder, config);

        return builder;
    }

    // ------------------------------ HTTPS 安全配置 ------------------------------

    /**
     * 配置 HTTPS 证书信任策略
     * <p>
     * 支持三种模式:
     * <ul>
     *     <li><b>调试模式</b>({@code debugMode=true}):
     *         <ul>
     *             <li>跳过所有证书验证(存在严重安全风险,仅限测试环境!)</li>
     *             <li>警告:可能导致中间人攻击,绝不能用于生产环境</li>
     *         </ul>
     *     </li>
     *     <li><b>自定义证书</b>({@code trustedCertificates 非空}):
     *         <ul>
     *             <li>仅信任指定的 PEM 格式证书</li>
     *             <li>适用于双向认证或自签名证书场景</li>
     *         </ul>
     *     </li>
     *     <li><b>系统默认</b>(默认模式):
     *         <ul>
     *             <li>使用设备/系统预装的 CA 证书</li>
     *             <li>适用于生产环境的标准 HTTPS 通信</li>
     *         </ul>
     *     </li>
     * </ul>
     * </p>
     *
     * @param builder OkHttpClient 构建器实例
     * @param config  配置参数(包含 HTTPS 相关配置)
     * @return 应用证书策略后的构建器实例
     * @throws RuntimeException 证书配置失败时抛出(包装底层异常)
     */
    private static OkHttpClient.Builder configSSL(OkHttpClient.Builder builder, OkHttpConfig config) {
        try {
            SSLContext sslContext;
            X509TrustManager trustManager;
            if (config.debugMode) {
                // 调试模式:禁用证书验证(风险提示:仅用于测试环境!)
                sslContext = SSLContext.getInstance("TLSv1.3");
                trustManager = new TrustAllManager();
                sslContext.init(null, new TrustManager[]{trustManager}, new SecureRandom());
                builder.sslSocketFactory(sslContext.getSocketFactory(), trustManager);
            } else if (config.trustedCertificates != null && config.trustedCertificates.length > 0) {
                // 自定义证书模式:使用指定的 PEM 证书
                trustManager = createCustomTrustManager(config.trustedCertificates);
                sslContext = SSLContext.getInstance("TLSv1.3");
                sslContext.init(null, new TrustManager[]{trustManager}, null);
                builder.sslSocketFactory(sslContext.getSocketFactory(), trustManager);
            } else {
                // 生产环境默认:使用系统信任的证书
                trustManager = getSystemTrustManager();
                sslContext = SSLContext.getInstance("TLSv1.3");
                sslContext.init(null, new TrustManager[]{trustManager}, null);
                builder.sslSocketFactory(sslContext.getSocketFactory(), trustManager);
            }
            // 允许所有主机名验证(需根据实际需求调整,此处为演示简化)
            builder.hostnameVerifier((hostname, session) -> true);
        } catch (Exception e) {
            throw new RuntimeException("HTTPS 证书配置失败", e);
        }
        return builder;
    }

    // region 安全组件

    /**
     * 调试模式专用:信任所有证书的管理器
     * <p>
     * 重写证书验证方法,跳过所有客户端和服务器证书检查
     * 警告:此实现存在严重安全漏洞,仅限测试环境使用!
     * </p>
     */
    @Deprecated
    private static class TrustAllManager implements X509TrustManager {
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) {
            // 客户端证书验证(此处无需处理)
        }

        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) {
            // 跳过服务器证书验证(调试模式专用)
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0]; // 返回空列表表示接受所有颁发者
        }
    }

    /**
     * 调试模式专用:创建忽略证书验证的 SSLSocketFactory
     * <p>
     * 警告:此模式会绕过所有证书验证,存在中间人攻击风险,仅限测试环境使用!
     * </p>
     *
     * @return 不安全的 SSLSocketFactory 实例
     * @throws Exception SSL 上下文初始化失败时抛出
     */
    private static SSLSocketFactory createInsecureSocketFactory() throws Exception {
        SSLContext context = SSLContext.getInstance("TLSv1.3");
        context.init(null, new TrustManager[]{new TrustAllManager()}, new SecureRandom());
        return context.getSocketFactory();
    }

    /**
     * 获取系统默认的证书信任管理器
     * <p>
     * 使用设备或系统预装的证书颁发机构 (CA) 列表
     * </p>
     *
     * @return 系统默认的 X509TrustManager 实例
     * @throws Exception 信任管理器初始化失败时抛出
     */
    private static X509TrustManager getSystemTrustManager() throws Exception {
        TrustManagerFactory factory = TrustManagerFactory.getInstance(
                TrustManagerFactory.getDefaultAlgorithm());
        factory.init((KeyStore) null);
        return (X509TrustManager) factory.getTrustManagers()[0];
    }

    /**
     * 创建自定义证书信任管理器(PEM 格式)
     * <p>
     * 将指定的证书添加到信任列表,用于验证服务器证书
     * </p>
     *
     * @param certificates PEM 格式的 X509 证书数组
     * @return 自定义的 X509TrustManager 实例
     * @throws Exception 密钥库或信任管理器初始化失败时抛出
     */
    private static X509TrustManager createCustomTrustManager(X509Certificate[] certificates)
            throws Exception {
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(null, null);
        for (int i = 0; i < certificates.length; i++) {
            keyStore.setCertificateEntry("cert-" + i, certificates[i]);
        }

        TrustManagerFactory factory = TrustManagerFactory.getInstance(
                TrustManagerFactory.getDefaultAlgorithm());
        factory.init(keyStore);
        return (X509TrustManager) factory.getTrustManagers()[0];
    }

    // endregion

    // region 拦截器
    private static class LoggingInterceptor implements Interceptor {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            long startNs = System.nanoTime();

            // 记录请求详情
            // log.debug("Request => {} {}\nHeaders: {}", request.method(), request.url(), request.headers());

            Response response = chain.proceed(request);
            long costMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs);

            // 记录响应指标
            // log.info("Response <= {} {} ({}ms)\nCode: {}", request.method(), request.url(), costMs, response.code());

            return response;
        }
    }

    /**
     * 失败重试拦截器(基于默认配置的最大重试次数)
     * <p>
     * 实现逻辑:
     * <ul>
     *     <li>对每个请求尝试 {@code maxRetries + 1} 次(包括首次)</li>
     *     <li>仅处理 {@link IOException}(网络层异常)</li>
     *     <li>成功响应({@code response.isSuccessful()})立即返回</li>
     * </ul>
     * </p>
     */
    private static class RetryInterceptor implements Interceptor {
        private final int maxRetries;  // 最大重试次数(不包含首次请求)

        /**
         * @param maxRetries 最大重试次数(建议 0-5,默认 3)
         */
        public RetryInterceptor(int maxRetries) {
            this.maxRetries = maxRetries;
        }

        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            IOException exception = null;

            for (int i = 0; i <= maxRetries; i++) {  // 包括首次请求,总尝试次数 maxRetries + 1
                try {
                    Response response = chain.proceed(request);
                    if (response.isSuccessful()) return response;
                    // 非成功响应不重试(如 4xx/5xx 错误,由上层处理)
                    return response;
                } catch (IOException e) {
                    exception = e;
                    // log.warn("请求失败(尝试 {}/{}): {}", i + 1, maxRetries + 1, e.getMessage());
                    System.out.println(String.format("请求失败(尝试 %d/%d): %s", i + 1, maxRetries + 1, e.getMessage()));
                }
            }

            throw exception != null ? exception : new IOException("网络请求无响应");
        }
    }
    // endregion

    // region 统一响应处理

    /**
     * 解析响应并处理异常
     * <p>
     * 自动关闭响应体,封装非成功状态码为 {@link HttpException}
     * </p>
     *
     * @param response OkHttp 响应实例(不可为 null)
     * @return 响应正文(UTF-8 字符串)
     * @throws IOException   网络异常或响应体为空
     * @throws HttpException 非 2xx 状态码(包含状态码和消息)
     */
    public static String parseResponse(Response response) throws IOException {
        try {
            if (!response.isSuccessful()) {
                throw new HttpException(response.code(),
                        "HTTP错误: " + response.code() + " - " + response.message());
            }

            ResponseBody body = response.body();
            if (body == null) throw new HttpException(500, "响应体为空");

            return body.string();
        } finally {
            response.close();
        }
    }

    /**
     * 自定义 HTTP 异常(包含状态码)
     */
    public static class HttpException extends IOException {
        private final int statusCode;  // HTTP 状态码(如 404, 500)

        public HttpException(int statusCode, String message) {
            super(message);
            this.statusCode = statusCode;
        }

        public int getStatusCode() {
            return statusCode;
        }
    }

    // endregion

    // region 链式调用

    /**
     * 链式请求构建器(支持 GET/POST 请求)
     * <p>
     * POST 提交 JSON 数据示例:
     * <pre>
     * String jsonBody = "{\"name\":\"Dolphin\",\"age\":18}";
     * String result = OkHttp_Util.post("https://api.post.com")
     *     .addHeader("Content-Type", "application/json")
     *     .jsonBody(jsonBody) // 设置 JSON 请求体
     *     .execute_Pro(); // 自动处理 200 以外状态码
     * </pre>
     * <p>
     * GET 请求带查询参数示例:
     * <pre>
     * Map<String, String> params = new HashMap<>();
     * params.put("key1", "value1");
     * params.put("key2", "value2");
     * String result = OkHttp_Util.get("https://api.get.com")
     *     .addUrlParam(params) // 批量添加查询参数
     *     .execute_Pro();
     * </pre>
     */
    public static class RequestChainBuilder {
        // region MediaType 常量
        // 定义 JSON 数据的媒体类型,字符集为 UTF-8
        private static final MediaType JSON_TYPE = MediaType.get("application/json; charset=utf-8");
        // 定义表单数据的媒体类型,字符集为 UTF-8
        private static final MediaType FORM_URLENCODED_TYPE = MediaType.get("application/x-www-form-urlencoded; charset=utf-8");
        // 定义纯文本数据的媒体类型,字符集为 UTF-8
        private static final MediaType TEXT_PLAIN_TYPE = MediaType.get("text/plain; charset=utf-8");
        // 定义 XML 数据的媒体类型,字符集为 UTF-8
        private static final MediaType XML_TYPE = MediaType.get("application/xml; charset=utf-8");
        // endregion

        private final OkHttpClient client;       // 使用的 OkHttpClient 实例(默认或自定义)
        private final HttpUrl.Builder urlBuilder; // URL 构建器(包含基础 URL 和查询参数)
        private final Request.Builder requestBuilder; // 请求构建器(包含头信息和方法)
        private RequestBody requestBody;         // 请求体(仅 POST/PUT 等方法需要)

        /**
         * 私有构造方法(内部使用,外部通过工厂方法创建)
         *
         * @param url    基础 URL(不可为 null,需包含协议如 http://)
         * @param client OkHttpClient 实例(默认或自定义)
         * @throws NullPointerException 当 url 或 client 为 null 时抛出
         */
        private RequestChainBuilder(String url, OkHttpClient client) {
            // 确保 client 不为 null,若为 null 则抛出异常
            this.client = Objects.requireNonNull(client, "client 不能为 null");
            // 解析 URL 并创建 URL 构建器,若 URL 格式错误则抛出异常
            this.urlBuilder = Objects.requireNonNull(HttpUrl.parse(url), "url 格式错误").newBuilder();
            // 创建请求构建器
            this.requestBuilder = new Request.Builder();
        }

        /**
         * 添加单个 URL 查询参数(链式调用)。
         *
         * @param key   参数名,不可为 null
         * @param value 参数值,可为 null(将被编码为空字符串)
         * @return 当前构建器实例,支持链式调用
         * @throws IllegalArgumentException 当 key 为 null 时抛出
         */
        public RequestChainBuilder addUrlParam(String key, String value) {
            // 确保参数名不为空,若为空则抛出异常
            if (key == null) throw new IllegalArgumentException("参数名不能为空");
            // 向 URL 构建器中添加查询参数,若值为 null 则编码为空字符串
            urlBuilder.addQueryParameter(key, value != null ? value : "");
            // 返回当前构建器实例,以支持链式调用
            return this;
        }

        /**
         * 添加单个请求头字段(链式调用)。
         *
         * @param key   头字段名,不可为 null
         * @param value 头字段值,可为 null(OkHttp 会自动处理 null 值)
         * @return 当前构建器实例,支持链式调用
         * @throws IllegalArgumentException 当 key 为 null 时抛出
         */
        public RequestChainBuilder addHeader(String key, String value) {
            if (key == null) throw new IllegalArgumentException("头字段名不能为空");
            requestBuilder.addHeader(key, value);
            return this;
        }

        /**
         * 批量添加 URL 参数
         *
         * @param params 包含要添加的 URL 参数的 Map
         * @return 当前构建器实例
         */
        public RequestChainBuilder addUrlParam(Map<String, String> params) {
            // 若参数不为空,则遍历参数并调用 addUrlParam 方法添加每个参数
            if (params != null) {
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    addUrlParam(entry.getKey(), entry.getValue());
                }
            }
            // 返回当前构建器实例,以支持链式调用
            return this;
        }

        /**
         * 批量添加请求头
         *
         * @param headers 包含要添加的请求头的 Map
         * @return 当前构建器实例
         */
        public RequestChainBuilder addHeaders(Map<String, String> headers) {
            // 若头信息不为空,则遍历头信息并调用 addHeader 方法添加每个头信息
            if (headers != null) {
                for (Map.Entry<String, String> entry : headers.entrySet()) {
                    addHeader(entry.getKey(), entry.getValue());
                }
            }
            // 返回当前构建器实例,以支持链式调用
            return this;
        }

        /****************** GET请求封装 ********************/
        /**
         * 设置请求方法为 GET
         * GET 请求不需要请求体,调用后可继续添加查询参数或请求头
         *
         * @return 当前构建器实例
         */
        public RequestChainBuilder get() {
            // 向请求构建器中设置请求方法为 GET
            requestBuilder.get();
            // 返回当前构建器实例,以支持链式调用
            return this;
        }

        /****************** POST请求封装 ********************/
        /**
         * 设置请求方法为 POST
         * 调用后需通过 {@link #formData(Map)}、{@link #jsonBody(String)} 等方法设置请求体
         *
         * @return 当前构建器实例
         */
        public RequestChainBuilder post() {
            // 默认设置空请求体
            this.requestBody = RequestBody.create(null, new byte[0]);
            // 返回当前构建器实例,以支持链式调用
            return this;
        }

        // ------------------------------ Body 参数配置 ------------------------------

        /**
         * 设置 FormData 表单参数(multipart/form-data)
         * 自动构建 {@link MultipartBody},媒体类型为 {@code multipart/form-data}
         *
         * @param params 表单参数(键值对)
         * @return 当前实例
         */
        public RequestChainBuilder formData(Map<String, String> params) {
            // 参数校验
            if (params == null) throw new IllegalArgumentException("参数 params 不能为空");

            // 创建 MultipartBody 构建器,并设置媒体类型为 multipart/form-data
            MultipartBody.Builder bodyBuilder = new MultipartBody.Builder()
                    .setType(MultipartBody.FORM);
            // 遍历参数并添加到 MultipartBody 构建器中
            params.forEach(bodyBuilder::addFormDataPart);
            // 构建请求体
            this.requestBody = bodyBuilder.build();
            // 返回当前构建器实例,以支持链式调用
            return this;
        }

        /**
         * 设置 multipart/form-data 表单参数(含文件上传)
         * <p>
         * 示例:上传单个文件
         * <pre>
         * File avatar = new File("avatar.png");
         * MediaType imageType = MediaType.parse("image/png");
         * String uploadResult = OkHttp_Util.post("https://api.upload.com")
         *     .formData("file", avatar, imageType) // 文件参数
         *     .addFormDataPart("username", "dolphin") // 普通表单参数(需配合 MultipartBody.Builder)
         *     .execute_Pro();
         * </pre>
         *
         * @param key       表单字段名
         * @param file      上传文件
         * @param mediaType 文件类型(如 MediaType.parse("image/png"))
         * @return 当前构建器实例
         */
        public RequestChainBuilder formData(String key, File file, MediaType mediaType) {
            // 参数校验
            if (key == null) throw new IllegalArgumentException("参数 key 不能为空");
            if (file == null) throw new IllegalArgumentException("参数 file 不能为空");
            if (mediaType == null) throw new IllegalArgumentException("参数 mediaType 不能为空");

            // 创建 MultipartBody 构建器,并设置媒体类型为 multipart/form-data
            MultipartBody.Builder builder = new MultipartBody.Builder()
                    .setType(MultipartBody.FORM)
                    // 添加文件部分,设置 Content-Disposition 头信息
                    .addPart(
                            Headers.of("Content-Disposition", "form-data; name=\"" + key + "\"; filename=\"" + file.getName() + "\""),
                            RequestBody.create(mediaType, file)
                    );
            // 构建请求体
            this.requestBody = builder.build();
            // 返回当前构建器实例,以支持链式调用
            return this;
        }

        /**
         * 设置 x-www-form-urlencoded 表单参数
         * 自动构建 {@link FormBody},媒体类型为 {@code application/x-www-form-urlencoded}
         *
         * @param params 表单参数(键值对)
         * @return 当前实例
         */
        public RequestChainBuilder formUrlEncoded(Map<String, String> params) {
            // 参数校验
            if (params == null) throw new IllegalArgumentException("参数 params 不能为空");
            // 创建 FormBody 构建器
            FormBody.Builder bodyBuilder = new FormBody.Builder();
            // 遍历参数并添加到 FormBody 构建器中
            params.forEach(bodyBuilder::add);
            // 构建请求体
            this.requestBody = bodyBuilder.build();
            // 返回当前构建器实例,以支持链式调用
            return this;
        }

        /**
         * 设置 Raw JSON 数据
         * 自动设置媒体类型为 {@code application/json; charset=utf-8}
         *
         * @param json JSON 字符串
         * @return 当前实例
         */
        public RequestChainBuilder jsonBody(String json) {
            // 参数校验
            if (json == null) throw new IllegalArgumentException("参数 json 不能为空");
            // 创建 JSON 格式的请求体
            this.requestBody = RequestBody.create(json, JSON_TYPE);
            // 返回当前构建器实例,以支持链式调用
            return this;
        }

        /**
         * 设置 Raw 文本数据
         * 自动设置媒体类型为 {@code text/plain; charset=utf-8}
         *
         * @param text 文本内容
         * @return 当前实例
         */
        public RequestChainBuilder rawText(String text) {
            // 参数校验
            if (text == null) throw new IllegalArgumentException("参数 text 不能为空");
            // 创建纯文本格式的请求体
            this.requestBody = RequestBody.create(text, TEXT_PLAIN_TYPE);
            // 返回当前构建器实例,以支持链式调用
            return this;
        }

        /**
         * 设置 Raw XML 数据
         * 自动设置媒体类型为 {@code application/xml; charset=utf-8}
         *
         * @param xml XML 字符串
         * @return 当前实例
         */
        public RequestChainBuilder rawXml(String xml) {
            // 参数校验
            if (xml == null) throw new IllegalArgumentException("参数 xml 不能为空");
            // 创建 XML 格式的请求体
            this.requestBody = RequestBody.create(xml, XML_TYPE);
            // 返回当前构建器实例,以支持链式调用
            return this;
        }

        /**
         * 设置二进制数据
         * 媒体类型为 {@code application/octet-stream}
         *
         * @param data 二进制字节数组
         * @return 当前实例
         */
        public RequestChainBuilder binaryBody(byte[] data) {
            // 参数校验
            if (data == null) throw new IllegalArgumentException("参数 data 不能为空");
            // 创建二进制格式的请求体
            this.requestBody = RequestBody.create(data, MediaType.get("application/octet-stream"));
            // 返回当前构建器实例,以支持链式调用
            return this;
        }

        /**
         * 执行同步请求并返回原始响应对象。
         * <p>
         * 适用于需要手动处理响应状态码和响应体的场景,需调用者手动关闭响应体。
         *
         * @return OkHttp 的 {@link Response} 对象
         * @throws IOException 网络异常、请求超时或服务器错误
         */
        public Response execute() throws IOException {
            // 构建最终URL
            HttpUrl httpUrl = urlBuilder.build();

            // POST请求设置请求体
            if (requestBody != null) {
                // 若请求体不为空,则设置请求方法为 POST 并设置请求体
                requestBuilder.method("POST", requestBody);
            }

            // 设置URL并构建请求
            Request request = requestBuilder.url(httpUrl).build();

            // 执行请求并返回响应
            return client.newCall(request).execute();
        }

        /**
         * 执行同步请求并返回处理后的响应字符串(自动处理非成功状态码)。
         * <p>
         * 功能包括:
         * <ul>
         *     <li>自动关闭响应体(通过 try-with-resources)</li>
         *     <li>检查响应状态码,非 2xx 状态码抛出 {@link OkHttp_Util.HttpException}</li>
         *     <li>将响应体转换为 UTF-8 编码的字符串</li>
         * </ul>
         * 自动关闭响应体,处理非成功状态码({@code response.isSuccessful()})
         * </p>
         *
         * @return 响应正文(UTF-8 字符串)
         * @throws IOException               网络异常、响应体解析失败或 I/O 错误
         * @throws OkHttp_Util.HttpException 当响应状态码非 2xx 时抛出,包含状态码和错误消息
         */
        public String execute_Pro() throws IOException {
            // 构建最终URL
            HttpUrl httpUrl = urlBuilder.build();

            // POST请求设置请求体
            if (requestBody != null) {
                // 若请求体不为空,则设置请求方法为 POST 并设置请求体
                requestBuilder.method("POST", requestBody);
            }

            // 设置URL并构建请求
            Request request = requestBuilder.url(httpUrl).build();

            // 执行请求并自动关闭响应体
            try (Response response = client.newCall(request).execute()) {
                // 解析响应并返回响应正文
                return OkHttp_Util.parseResponse(response);
            }
        }

        /**
         * 执行异步请求,通过回调处理响应结果。
         * <p>
         * 支持处理成功响应({@link Callback#onResponse(Call, Response)})和失败情况({@link Callback#onFailure(Call, IOException)})。
         * <p>
         * **注意**:异步请求不会自动关闭响应体,需在 {@link Callback#onResponse(Call, Response)} 中手动关闭。
         *
         * @param callback 异步回调接口,不可为 null
         * @throws NullPointerException 当 callback 为 null 时抛出
         */
        public void enqueue(Callback callback) {
            try {
                // 检查 OkHttpClient 实例是否为 null
                if (client == null) {
                    // 若为 null,则调用回调的 onFailure 方法并传入异常信息
                    callback.onFailure(null, new IOException("OkHttpClient 实例为 null"));
                    return;
                }
                // 构建请求
                Request request = requestBuilder.url(urlBuilder.build()).build();
                // 检查请求是否为 null
                if (request == null) {
                    // 若为 null,则调用回调的 onFailure 方法并传入异常信息
                    callback.onFailure(null, new IOException("请求构建失败,Request 为 null"));
                    return;
                }
                // 执行异步请求
                client.newCall(request).enqueue(callback);
            } catch (IllegalStateException e) {
                // 记录 URL 构建失败的日志
                // log.error("URL构建失败", e);
                System.err.println("URL构建失败: " + e.getMessage());
                // 调用回调的 onFailure 方法并传入异常信息
                callback.onFailure(null, new IOException("URL构建失败"));
            } catch (Exception e) {
                // 记录异步请求失败的日志
                // log.error("异步请求失败", e);
                System.err.println("异步请求失败: " + e.getMessage());
                // 调用回调的 onFailure 方法并传入异常信息
                callback.onFailure(null, new IOException("异步请求失败"));
            }
        }
    }

    /**
     * 重载工厂方法:创建一个 GET 请求的链式构建器
     *
     * @param url 请求的 URL
     * @return 链式构建器实例
     */
    public static RequestChainBuilder get(String url) {
        // 创建一个 RequestChainBuilder 实例并设置请求方法为 GET
        return new RequestChainBuilder(url, OkHttp_Util.getDefaultInstance()).get();
    }

    /**
     * 重载工厂方法:创建一个 POST 请求的链式构建器
     *
     * @param url 请求的 URL
     * @return 链式构建器实例
     */
    public static RequestChainBuilder post(String url) {
        // 创建一个 RequestChainBuilder 实例并设置请求方法为 POST
        return new RequestChainBuilder(url, OkHttp_Util.getDefaultInstance()).post();
    }

    /**
     * 重载工厂方法:支持传入自定义 OkHttpClient 实例,创建一个使用自定义 OkHttpClient 实例的 GET 请求的链式构建器
     *
     * @param url    请求的 URL
     * @param client 自定义的 OkHttpClient 实例
     * @return 链式构建器实例
     */
    public static RequestChainBuilder get(String url, OkHttpClient client) {
        // 创建一个 RequestChainBuilder 实例并设置请求方法为 GET,使用自定义的 OkHttpClient 实例
        return new RequestChainBuilder(url, client).get();
    }

    /**
     * 重载工厂方法:支持传入自定义 OkHttpClient 实例,创建一个使用自定义 OkHttpClient 实例的 POST 请求的链式构建器
     *
     * @param url    请求的 URL
     * @param client 自定义的 OkHttpClient 实例
     * @return 链式构建器实例
     */
    public static RequestChainBuilder post(String url, OkHttpClient client) {
        // 创建一个 RequestChainBuilder 实例并设置请求方法为 POST,使用自定义的 OkHttpClient 实例
        return new RequestChainBuilder(url, client).post();
    }
    // endregion

    public static void main(String[] args) throws IOException {
        // 使用默认配置
        OkHttpClient defaultClient = OkHttp_Util.getDefaultInstance();


        // -------------------------------------------------------------------------------
        String responseDefault = OkHttp_Util.get("https://api.example.com")
                .addUrlParam("key", "value")
                .execute_Pro();


        // -------------------------------------------------------------------------------
        // 创建自定义配置
        OkHttpClient.Builder customBuilder = OkHttp_Util.customBuilder()
                .addInterceptor(new LoggingInterceptor())
                .connectTimeout(30, TimeUnit.SECONDS);

        // 提交并实例化自定义配置(单例)
        OkHttp_Util.buildCustomInstance(customBuilder);

        // 获取自定义配置实例
        OkHttpClient customClient = OkHttp_Util.getCustomInstance();
        String responseCustom = OkHttp_Util.get("https://api.example.com", customClient)
                .addUrlParam("key", "value")
                .execute_Pro();
    }
}

六、总结

本工具类通过封装OkHttp的复杂配置,提供以下优势:

  • 开发效率提升:链式API简化网络请求编写
  • 可维护性强:统一配置入口,修改全局参数方便
  • 安全性增强:标准化HTTPS证书管理
  • 健壮性保障:内置重试机制和异常处理

适合中大型项目作为基础网络组件使用,建议根据实际业务需求调整超时时间和重试策略。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值