关于 okhttp3-5.x
okhttp3-5.x 是使用 OkHttp 5.x 的参考技能;OkHttp 是面向 Java 和 Android 的 HTTP 客户端。内容涵盖请求处理、连接、缓存、拦截器、TLS 配置、监控及使用 MockWebServer 测试。
主要功能
- 01同步与异步 HTTP 调用
- 02HTTP/2 与连接池
- 03响应缓存与拦截器
- 04TLS 配置与证书固定
- 05调用监控与 MockWebServer 测试
适用场景
- 01构建 Java 或 Android REST API 客户端
- 02配置请求重试、认证和重定向
- 03添加响应缓存或调用日志
- 04使用 MockWebServer 测试 HTTP 客户端
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ full-stack-skills/ java-skills --skill okhttp3-5.x安装后在 Claude Code 中输入/okhttp3-5.x确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
examples/interceptors-examples.mdhttps-examples.mdbasic-usage.mdcaching-examples.mdreferences/events.mdconnections.mdhttps.mdconfiguration.mdcalls.mdsecurity.mdcaching.mdinterceptors.mdrecipes.md详细介绍
OkHttp 5.x 参考(v5.4.0)
OkHttp 默认是一款高效的 HTTP 客户端,支持 HTTP/2、连接池、透明 GZIP 和响应缓存。它会自动恢复常见的连接问题,并在首次连接失败时尝试其他地址。
官方文档来源
所有权威信息均可在 OkHttp 官方网站查阅:
OkHttp 遵循的 RFC 标准:
- HTTP 语义 — RFC 9110
- HTTP 缓存 — RFC 9111
- HTTP/1.1 — RFC 9112
- HTTP/2 — RFC 9113
- WebSockets — RFC 6455
- SSE — 服务器发送事件
- Happy Eyeballs — RFC 6555
能力边界
✅ 擅长领域
- 支持 HTTP/2 — 发往同一主机的所有请求共用一个套接字
- 连接池 — 降低延迟并自动复用连接
- 透明 GZIP — 自动缩小下载内容的体积
- 响应缓存 — 避免重复请求时访问网络
- 拦截器 — 监控、重写和重试调用(应用层 + 网络层)
- 快速回退(Happy Eyeballs RFC 6555)— 并发尝试 IPv4/IPv6 连接
- TLS 1.3、ALPN、证书固定
- EventListener API — 捕获 HTTP 调用的指标
- MockWebServer — 测试 HTTP/HTTPS/HTTP/2 客户端
- 支持 GraalVM Native Image
- 支持 Java 9 模块(5.2+)
- 用于依赖管理的 BOM
⚠️ 要求
- Java 8+ 或 Android 5.0+(API 级别 21+)
- Kotlin Multiplatform:Maven 项目必须使用
okhttp-jvm构件(而非okhttp) - 依赖 Okio 和 Kotlin 标准库(传递依赖)
- 使用证书固定时:需要与服务器 TLS 管理员协调
❌ 不适用范围(及替代方案)
- 带请求体的 GET — OkHttp 不允许 GET 请求携带请求体(请使用 POST)
- 自定义缓存实现 — Cache 不是接口(自定义缓存逻辑请使用拦截器)
- 高度无效的 HTTP 请求 — OkHttp 严格遵循 RFC
- 旧版 Android(低于 5.0)— API 9+ 请使用 OkHttp 3.12.x 分支
- 旧版 Java(低于 8)— Java 7+ 请使用 OkHttp 3.12.x 分支
以下情况不应使用 OkHttp:
- 带请求体的 GET 请求(请改用 POST)
- 自定义缓存实现(请使用拦截器)
- 无效的 HTTP 请求(OkHttp 严格遵循 RFC)
- Android < 5.0(请使用 OkHttp 3.12.x)
- Java < 8(请使用 OkHttp 3.12.x)
何时使用此技能
当用户需要以下功能时,请使用此技能:
- 在 Java 或 Android 中发送 HTTP/HTTPS 请求
- 构建带连接池的 REST API 客户端
- 实现响应缓存
- 添加请求/响应拦截器(日志记录、身份验证、压缩)
- 配置 TLS 版本和密码套件
- 固定证书以确保安全
- 使用 EventListener 监控 HTTP 调用性能
- 使用 MockWebServer 测试 HTTP 客户端
- 处理重定向、重试和身份验证质询
- 使用 HTTP/2 多路复用
5.x 新功能(相较于 4.x)
OkHttp 5.x 的主要变更:
- Kotlin Multiplatform — 提供独立的 JVM 和 Android 构件(Maven 使用
okhttp-jvm) - Happy Eyeballs(RFC 6555) — 默认启用快速回退;并发尝试 IPv4/IPv6
- MockWebServer 3 — 新坐标(
mockwebserver3),不依赖 JUnit 4,API 不可变 - GraalVM Native Image — 自动支持;示例请参阅
okcurl模块 - Java 9 模块(JPMS) — 提供规范的
module-info.java文件(5.2+) - 虚拟线程 — 支持 Java 21 虚拟线程(使用 Lock/Condition,而非 synchronized)
- 拦截器增强功能(5.4) — 拦截器现在可以覆盖 OkHttpClient.Builder 设置
- 调用标签(5.3) — 为 Call 附加特定于应用的元数据
- Zstd 压缩(5.2) — 提供
okhttp-zstd模块以支持 Zstandard 压缩 - QUERY HTTP 方法(5.2) — 支持 QUERY 方法
- HTTP 101 响应(5.2) — 提供用于连接升级的 Response.socket
快速开始
Gradle:
dependencies {
implementation(platform("com.squareup.okhttp3:okhttp-bom:5.4.0"))
implementation("com.squareup.okhttp3:okhttp")
implementation("com.squareup.okhttp3:logging-interceptor")
}
Maven(JVM — 必须使用 okhttp-jvm):
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp-bom</artifactId>
<version>5.4.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp-jvm</artifactId>
</dependency>
</dependencies>
最简 GET 请求:
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url("https://api.example.com/users").build();
try (Response response = client.newCall(request).execute()) {
System.out.println(response.body().string());
}
最简 JSON POST 请求:
RequestBody body = RequestBody.create("{\"name\":\"Alice\"}", MediaType.get("application/json"));
Request request = new Request.Builder().url("https://api.example.com/users").post(body).build();
try (Response response = client.newCall(request).execute()) {
System.out.println(response.body().string());
}
工作流
步骤 1. 确认环境 — 检查 Java 8+ 或 Android 5+,选择 Maven(okhttp-jvm)或 Gradle(okhttp)
步骤 2. 配置 OkHttpClient — 设置超时、连接池、缓存、拦截器和 TLS
步骤 3. 构建 Request — 设置 URL、方法、请求头和请求体
步骤 4. 执行 Call — 同步(execute())或异步(enqueue())
步骤 5. 处理 Response — 检查状态、读取请求体并处理错误
重要:OkHttpClient 配置
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.callTimeout(60, TimeUnit.SECONDS) // Entire call timeout
.connectionPool(new ConnectionPool(5, 5, TimeUnit.MINUTES))
.cache(new Cache(new File("cache-dir"), 50L * 1024L * 1024L)) // 50 MiB
.addInterceptor(new LoggingInterceptor()) // Application interceptor
.addNetworkInterceptor(new NetworkInterceptor()) // Network interceptor
.followRedirects(true)
.followSslRedirects(true)
.retryOnConnectionFailure(true)
.build();
主要配置选项:
| Builder 方法 | 作用 | 默认值 |
|---|---|---|
connectTimeout(int, TimeUnit) | TCP 连接超时 | 10 秒 |
readTimeout(int, TimeUnit) | Socket 读取超时 | 10 秒 |
writeTimeout(int, TimeUnit) | Socket 写入超时 | 10 秒 |
callTimeout(int, TimeUnit) | 整个调用的超时(所有步骤) | 不限 |
connectionPool(ConnectionPool) | 连接池设置 | 5 个空闲连接,保活 5 分钟 |
cache(Cache) | 响应缓存(默认关闭) | null |
followRedirects(boolean) | 跟随 HTTP 重定向 | true |
followSslRedirects(boolean) | 跟随 HTTPS↔HTTP 重定向 | true |
retryOnConnectionFailure(boolean) | 在连接失效时重试 | true |
dns(Dns) | 自定义 DNS 解析器 | 系统 DNS |
proxy(Proxy) | 单个代理 | null(直连) |
proxySelector(ProxySelector) | 按请求选择代理 | 系统默认值 |
authenticator(Authenticator) | 处理 HTTP 身份验证质询 | 无 |
certificatePinner(CertificatePinner) | 证书固定 | 无 |
sslSocketFactory(SSLSocketFactory, X509TrustManager) | 自定义 TLS | 平台默认值 |
connectionSpecs(List<ConnectionSpec>) | TLS 版本和密码套件 | MODERN_TLS |
eventListenerFactory(EventListener.Factory) | 事件监控 | 无 |
完整参考请参阅 references/configuration.md。
重要:发送请求
构建请求:
Request request = new Request.Builder()
.url("https://api.example.com/users/1")
.header("Authorization", "Bearer token123")
.addHeader("Accept", "application/json")
.get()
.build();
发送带 JSON 请求体的 POST 请求:
RequestBody body = RequestBody.create(jsonString, MediaType.get("application/json"));
Request request = new Request.Builder()
.url("https://api.example.com/users")
.post(body)
.build();
发送带表单数据的 POST 请求:
RequestBody formBody = new FormBody.Builder()
.add("username", "alice")
.add("password", "secret")
.build();
多部分上传:
RequestBody fileBody = RequestBody.create(new File("photo.jpg"), MediaType.get("image/jpeg"));
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("title", "My Photo")
.addFormDataPart("photo", "photo.jpg", fileBody)
.build();
PUT/DELETE、请求/响应生命周期请参阅 references/calls.md。
重要:处理响应
同步:
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
String body = response.body().string();
int code = response.code();
String contentType = response.header("Content-Type");
}
异步:
client.newCall(request).enqueue(new Callback() {
@Override public void onFailure(Call call, IOException e) { e.printStackTrace(); }
@Override public void onResponse(Call call, Response response) throws IOException {
try (ResponseBody body = response.body()) {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println(body.string());
}
}
});
后续处理、重试和 Dispatcher 请参阅 references/calls.md。
重要:拦截器
应用拦截器 — 即使响应来自缓存,也会看到原始请求:
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new LoggingInterceptor())
.build();
网络拦截器 — 会看到实际的网络请求(包括 OkHttp 添加的请求头):
OkHttpClient client = new OkHttpClient.Builder()
.addNetworkInterceptor(new LoggingInterceptor())
.build();
日志拦截器(内置):
import okhttp3.logging.HttpLoggingInterceptor;
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
应用拦截器与网络拦截器的区别、GzipRequestInterceptor 请参阅 references/interceptors.md。
关键:缓存
启用缓存:
OkHttpClient client = new OkHttpClient.Builder()
.cache(new Cache(new File("cache-dir"), 50L * 1024L * 1024L)) // 50 MiB
.build();
缓存事件: CacheHit、CacheMiss、CacheConditionalHit
清理缓存:
cache.evictAll(); // Clear all
Iterator<String> urlIterator = cache.urls();
while (urlIterator.hasNext()) {
if (urlIterator.next().startsWith("https://api.example.com/")) urlIterator.remove();
}
有关淘汰和故障排查,请参阅 references/caching.md。
关键:连接
OkHttp 使用分层模型:URL → Address → Route → Connection
- URL:资源标识符(协议、主机、路径)
- Address:Web 服务器 + 静态配置(端口、TLS 设置、协议)
- Route:动态信息(特定 IP、代理、TLS 版本)
- Connection:实际的 TCP 套接字(会被放入连接池并重复使用)
快速回退(Happy Eyeballs,5.0+):
- 同时尝试 IPv6 和 IPv4
- 保留第一个成功的连接
- 延迟 250ms 后取消其他尝试
有关连接池和快速回退的详情,请参阅 references/connections.md。
关键:HTTPS/TLS
4 种内置 ConnectionSpec:
RESTRICTED_TLS— 最严格,适用于合规要求MODERN_TLS— 默认选项,适用于安全的现代服务器COMPATIBLE_TLS— 适用于较旧但仍安全的服务器CLEARTEXT— 仅用于 http:// URL
回退配置:
OkHttpClient client = new OkHttpClient.Builder()
.connectionSpecs(Arrays.asList(ConnectionSpec.MODERN_TLS, ConnectionSpec.COMPATIBLE_TLS))
.build();
证书固定:
OkHttpClient client = new OkHttpClient.Builder()
.certificatePinner(
new CertificatePinner.Builder()
.add("publicobject.com", "sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=")
.build())
.build();
有关 TLS 调试、自定义 TrustManager 和密码套件,请参阅 references/https.md。
关键:常用模式
| 模式 | 描述 |
|---|---|
| 同步 GET | client.newCall(request).execute() |
| 异步 GET | client.newCall(request).enqueue(callback) |
| POST 字符串/文件 | RequestBody.create(content, mediaType) |
| POST 表单 | FormBody.Builder().add(name, value) |
| 多部分上传 | MultipartBody.Builder().addFormDataPart(...) |
| 单次调用配置 | client.newBuilder().readTimeout(...).build() |
| 身份验证 | OkHttpClient.Builder().authenticator(...) |
| 取消 | call.cancel() |
| 上传进度 | 使用 ForwardingSink 封装 RequestBody |
完整代码示例请参阅 references/recipes.md。
关键:安全
- TLS 配置 — 使用
ConnectionSpec.MODERN_TLS(默认);较旧的服务器可回退到COMPATIBLE_TLS - 证书固定 — 使用
CertificatePinner限制受信任的 CA - 自定义 TrustManager — 用自定义 CA 替换平台 CA(需要服务器 TLS 管理员批准)
- Conscrypt — 通过 Conscrypt provider 使用 BoringSSL,以确保跨平台 TLS 一致
有关 TLS 历史和 provider 配置,请参阅 references/security.md。
关键:事件(EventListener)
事件顺序(调用成功):
callStart → dnsStart → dnsEnd → connectStart → secureConnectStart → secureConnectEnd → connectEnd → connectionAcquired → requestHeadersStart → requestHeadersEnd → responseHeadersStart → responseHeadersEnd → responseBodyStart → responseBodyEnd → connectionReleased → callEnd
连接池连接(跳过连接事件):
callStart → connectionAcquired → requestHeadersStart → requestHeadersEnd → responseHeadersStart → responseHeadersEnd → responseBodyStart → responseBodyEnd → connectionReleased → callEnd
并发调用的工厂:
EventListener.Factory factory = new EventListener.Factory() {
@Override public EventListener create(Call call) {
return new TimingEventListener();
}
};
有关完整的 EventListener 代码、失败/重试事件和 10% 采样,请参阅 references/events.md。
关键:MockWebServer
基本用法:
MockWebServer server = new MockWebServer();
server.enqueue(new MockResponse().setBody("Hello World!"));
server.start();
Request request = new Request.Builder().url(server.url("/")).build();
try (Response response = client.newCall(request).execute()) {
assertEquals("Hello World!", response.body().string());
}
server.shutdown();
Maven(使用 mockwebserver3):
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>mockwebserver3</artifactId>
<scope>test</scope>
</dependency>
有关 RecordedRequest 验证,请参阅 references/calls.md。
快速修复
| 错误 | 原因 | 修复方法 |
|---|---|---|
java.lang.NoClassDefFoundError: kotlin/jvm/internal/... | 缺少 Kotlin stdlib | OkHttp 5.x 是 KMP;确保在 Maven 中使用 okhttp-jvm,或在 Gradle 中使用 okhttp |
SSLHandshakeException | TLS 版本不匹配 | 检查 ConnectionSpec;尝试使用 COMPATIBLE_TLS 作为回退 |
SocketTimeoutException | 服务端响应太慢 | 增大 readTimeout 或 callTimeout |
ConnectionPool 耗尽 | 并发请求过多 | 增大连接池容量,或使用带有 Dispatcher 限制的异步调用 |
IllegalStateException: cache is closed | 缓存目录冲突 | 确保每个目录只使用一个 Cache 实例 |
Certificate pinning failure | 证书固定值不匹配 | 证书轮换后更新固定值 |
IOException: Canceled | 调用已取消 | 检查取消逻辑;不要过早取消 |
ProtocolException: HTTP/209 | HTTP 方法无效 | OkHttp 严格遵循 RFC;带请求体时改用 POST,而不是 GET |
Maven okhttp 构件为空 | KMP 构件问题 | Maven 项目请使用 okhttp-jvm |
| GraalVM 原生镜像构建失败 | 缺少反射配置 | 参见 okcurl 模块中的 GraalVM 配置示例 |
注意事项
- Maven 必须使用
okhttp-jvm— OkHttp 5.x 是 Kotlin Multiplatform;在 Maven 中,okhttp构件为空。JVM 项目请使用okhttp-jvm。 - GET 不能带请求体 — OkHttp 严格遵循 HTTP RFC。带请求体的请求请使用 POST。
- 缓存默认关闭 — 必须在 OkHttpClient.Builder 中显式配置
Cache。 - 缓存目录为独占目录 — 每个目录只能对应一个 Cache 实例。不要共享目录。
- 完整读取响应 — 缓存响应需要完整读取;部分读取不会被缓存。
- 关闭 Response 请求体 — 始终关闭 Response(使用 try-with-resources),以避免连接泄漏。
- 应用拦截器与网络拦截器 — 应用拦截器只运行一次(即使使用缓存也是如此);网络拦截器会针对每次网络调用运行。
- 5.x 默认启用 Fast Fallback — 并发尝试 IPv4/IPv6。必要时可通过
fastFallback(false)禁用。 - ConnectionSpec 会随版本变化 — TLS 版本和密码套件可能会发生变化。请保持更新。
- 证书固定需要协调 — 需要服务器 TLS 管理员批准。证书轮换时必须更新固定值。
- Dispatcher 限制 — 默认值:每个主机并发 5 个,总计 64 个。通过
dispatcher(new Dispatcher(executorService))配置。 - 透明 GZIP — OkHttp 会自动添加
Accept-Encoding: gzip。在网络层,拦截器看到的是压缩数据。
参考
调用
- calls.md — 请求/响应生命周期、重写、后续请求、重试、Dispatcher
缓存
- caching.md — 缓存配置、EventListener 缓存事件、目录管理、淘汰
连接
- connections.md — URL/Address/Route/Connection 模型、连接池、Fast Fallback
事件
- events.md — EventListener、Factory、并发调用、失败/重试事件
HTTPS
- https.md — ConnectionSpec、TLS 调试、证书固定、自定义 TrustManager
拦截器
- interceptors.md — 应用拦截器与网络拦截器、请求/响应重写
示例
- recipes.md — 常见模式:GET、POST、表单、多部分、身份验证、上传进度
安全性
- security.md — TLS 配置历史、证书提供方、Conscrypt
配置
- configuration.md — OkHttpClient.Builder 完整参考、Maven/Gradle/BOM 依赖