Java扩展——OkHttp

📅 发布时间:2026/9/7 3:17:50
Java扩展——OkHttp
OkHttp1、核心特性与架构设计2、核心 API 分类列表全景图3、常用 API 与实战代码示例4、避坑指南与最佳实践OkHttp 是由 Square 公司开源的高性能 HTTP HTTP/2 客户端也是目前 Java / Android 生态中最主流、事实上的 HTTP 网络库标准Android 官方从 Android 4.4 起底层已将 HttpURLConnection 替换为 OkHttp 实现。1、核心特性与架构设计HTTP/2 与连接池支持共享同一个 Socket 连接大幅降低延迟与 TCP 握手开销。透明的 GZIP 压缩自动压缩请求体并解压响应体节省网络流量。响应缓存支持 HTTP 响应头的本地缓存避免重复的网络请求。拦截器链Interceptor Chain极其强大的责任链设计模式允许轻松插拔日志记录、统一 Token 注入、失败重试、自动重定向等功能。基于 Okio 的高性能 IO底层结合 Square 的 Okio 库在缓冲管理和内存占用上性能顶尖。2、核心 API 分类列表全景图核心类 (Class)角色与功能说明OkHttpClient全局单例配置中心。管理连接池、超时时间、拦截器、缓存等。通常全局共享一个实例。RequestHTTP 请求描述。使用 Builder 模式构建包含 URL、HTTP 方法、请求头Headers、请求体RequestBody。ResponseHTTP 响应结果。包含状态码Code、响应头、响应体ResponseBody。注意响应体流只能读取一次且必须关闭。Call请求执行任务。代表一个已准备就绪的 HTTP 请求可同步execute()或异步enqueue()执行支持取消操作。RequestBody请求体抽象。支持传输 JSON、Form 表单、Multipart 多部分文件上传、流式数据等。ResponseBody响应体抽象。支持将响应转为 String、byte[] 或 InputStream用于大文件下载。Interceptor拦截器接口。应用拦截器Application Interceptor与网络拦截器Network Interceptor的核心入口。3、常用 API 与实战代码示例依赖引入 (Maven / Gradle)dependencygroupIdcom.squareup.okhttp3/groupIdartifactIdokhttp/artifactIdversion4.12.0/version!-- 推荐使用 4.x/5.x 稳定版 --/dependency1. 初始化全局 OkHttpClient最佳实践OkHttpClient 内部拥有连接池和线程池千万不要在每次请求时 new OkHttpClient()必须作为单例复用或者通过 .newBuilder() 基于现有配置衍生新对象。importokhttp3.OkHttpClient;importjava.util.concurrent.TimeUnit;publicclassOkHttpConfig{// 全局单例publicstaticfinalOkHttpClientCLIENTnewOkHttpClient.Builder().connectTimeout(10,TimeUnit.SECONDS)// 连接超时.readTimeout(10,TimeUnit.SECONDS)// 读取超时.writeTimeout(10,TimeUnit.SECONDS)// 写入超时.retryOnConnectionFailure(true)// 失败重试.build();}2. 同步与异步 GET 请求① 同步 GET 请求 (execute)importokhttp3.Request;importokhttp3.Response;importokhttp3.ResponseBody;publicvoidsyncGetDemo(){RequestrequestnewRequest.Builder().url(https://api.github.com/users/octocat).header(User-Agent,OkHttp-Demo)// 添加 Header.build();// try-with-resources 自动关闭 Response / ResponseBody 释放底层 Sockettry(ResponseresponseOkHttpConfig.CLIENT.newCall(request).execute()){if(!response.isSuccessful()){System.err.println(请求失败, 状态码: response.code());return;}ResponseBodybodyresponse.body();if(body!null){StringjsonResultbody.string();// 获取字符串格式的响应体System.out.println(响应内容: jsonResult);}}catch(Exceptione){e.printStackTrace();}}② 异步 GET 请求 (enqueue)importokhttp3.Call;importokhttp3.Callback;importokhttp3.Request;importokhttp3.Response;importjava.io.IOException;publicvoidasyncGetDemo(){RequestrequestnewRequest.Builder().url(https://api.github.com/users/octocat).build();// 放入异步线程池队列中执行不阻塞当前线程OkHttpConfig.CLIENT.newCall(request).enqueue(newCallback(){OverridepublicvoidonFailure(Callcall,IOExceptione){System.err.println(网络请求异常: e.getMessage());}OverridepublicvoidonResponse(Callcall,Responseresponse)throwsIOException{try(ResponseBodybodyresponse.body()){if(response.isSuccessful()body!null){System.out.println(异步响应结果: body.string());}}}});}3. POST 请求 (JSON 表单提交)① 发送 JSON 数据 (MediaType)importokhttp3.MediaType;importokhttp3.Request;importokhttp3.RequestBody;importokhttp3.Response;publicvoidpostJsonDemo()throwsException{MediaTypeJSONMediaType.get(application/json; charsetutf-8);StringjsonString{\name\:\Alice\, \age\:25};// 构建 RequestBodyRequestBodybodyRequestBody.create(jsonString,JSON);RequestrequestnewRequest.Builder().url(https://httpbin.org/post).post(body).build();try(ResponseresponseOkHttpConfig.CLIENT.newCall(request).execute()){System.out.println(POST 返回: response.body().string());}}② 提交 Form 表单数据 (FormBody)importokhttp3.FormBody;importokhttp3.Request;importokhttp3.RequestBody;importokhttp3.Response;publicvoidpostFormDemo()throwsException{// 模拟常规 HTML 表单提交RequestBodyformBodynewFormBody.Builder().add(username,admin).add(password,123456).build();RequestrequestnewRequest.Builder().url(https://httpbin.org/post).post(formBody).build();try(ResponseresponseOkHttpConfig.CLIENT.newCall(request).execute()){System.out.println(Form 返回: response.body().string());}}4. 文件上传 (MultipartBody) 与 文件下载① Multipart 多部分文件上传importokhttp3.*;importjava.io.File;publicvoiduploadFileDemo(FileuploadFile)throwsException{RequestBodyfileBodyRequestBody.create(uploadFile,MediaType.parse(image/png));// 构建包含表单参数和文件对象的 MultipartBodyRequestBodymultipartBodynewMultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart(user,JohnDoe).addFormDataPart(avatar,uploadFile.getName(),fileBody).build();RequestrequestnewRequest.Builder().url(https://httpbin.org/post).post(multipartBody).build();try(ResponseresponseOkHttpConfig.CLIENT.newCall(request).execute()){System.out.println(文件上传响应: response.code());}}② 文件流下载importokhttp3.*;importjava.io.FileOutputStream;publicvoiddownloadFileDemo(StringfileUrl,FilesaveFile)throwsException{RequestrequestnewRequest.Builder().url(fileUrl).build();try(ResponseresponseOkHttpConfig.CLIENT.newCall(request).execute()){if(!response.isSuccessful())return;// 使用 InputStream 分块写入本地文件防止大文件导致 OOMtry(varisresponse.body().byteStream();varfosnewFileOutputStream(saveFile)){byte[]buffernewbyte[8192];intread;while((readis.read(buffer))!-1){fos.write(buffer,0,read);}}}}5. 核心高级功能拦截器Interceptor拦截器是 OkHttp 最强大的拓展机制。常用于统一添加认证 Token、打印日志、修改请求头等。importokhttp3.Interceptor;importokhttp3.OkHttpClient;importokhttp3.Request;importokhttp3.Response;importjava.io.IOException;// 1. 定义一个用于自动注入 Auth Token 的拦截器publicclassAuthInterceptorimplementsInterceptor{privatefinalStringtoken;publicAuthInterceptor(Stringtoken){this.tokentoken;}OverridepublicResponseintercept(Chainchain)throwsIOException{RequestoriginalRequestchain.request();// 拦截并修改 Request追加 Authorization 请求头RequestauthenticatedRequestoriginalRequest.newBuilder().header(Authorization,Bearer token).build();// 放行请求交给责任链中的下一个节点执行returnchain.proceed(authenticatedRequest);}}// 2. 挂载到 OkHttpClient 示例OkHttpClientclientWithAuthOkHttpConfig.CLIENT.newBuilder().addInterceptor(newAuthInterceptor(secret_token_123)).build();4、避坑指南与最佳实践务必显式关闭 Response 或 ResponseBodybody.string() 或 body.byteStream() 底层持有 Socket 连接流如果未关闭会导致连接无法复用并发生连接池/句柄泄漏。建议统一使用 try-with-resources 语法。body.string() 只能被调用一次调用 body.string() 后响应流的内容会被全部读取并从内存缓存中释放。第二次调用会直接抛出 IllegalStateException: closed。如果需要二次读取需在拦截器层缓存 Buffer。避免在大文件下载时使用 body.string() 或 body.bytes()这会将整个文件一次性全量载入 JVM 堆内存极易引发 OutOfMemoryErrorOOM。大文件应使用 body.byteStream() 流式边读边写。