废话不多说,直接上代码
java
public class OkHttpExample {
// 同步 GET 请求
private static void syncGet(String url) {
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(3, TimeUnit.SECONDS)
.readTimeout(3, TimeUnit.SECONDS)
.build();
Request request = new Request.Builder()
.url(url)
.addHeader("Accept", "application/json")
.build();
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
System.out.println("GET 成功: " + response.body().string());
} else {
System.err.println("GET 失败: HTTP " + response.code());
}
} catch (IOException e) {
System.err.println("网络异常: " + e.getMessage());
}
}
}
这样存在一个问题,不停地实例化OkHttpClient,这样会浪费资源,且在高并发下,会存在性能隐患。所以,以上代码可以优化为下面这样子
java
public class OkHttpExample {
private static final OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(3, TimeUnit.SECONDS)
.readTimeout(3, TimeUnit.SECONDS)
.build();
// GET 请求
private static void syncGet(String url) {
Request request = new Request.Builder()
.url(url)
.addHeader("Accept", "application/json")
.build();
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
System.out.println("GET 成功: " + response.body().string());
} else {
System.err.println("GET 失败: HTTP " + response.code());
}
} catch (IOException e) {
System.err.println("网络异常: " + e.getMessage());
}
}
}
这样是不是没有优化空间了呢?看源码后,其实还有进一步代码空间,就okhttp3.ConnectionPool,这个就是连接池,这也就是不建议重复实例化OkHttpClient原因之一。
java
public ConnectionPool() {
this(5, 5, TimeUnit.MINUTES);
}
默认是设置5,对于绝大部分场景已经够用了,但如果还想进一步优化,可以修改成这样
java
public class OkHttpExample {
private static final OkHttpClient client = new OkHttpClient.Builder()
.connectionPool(new ConnectionPool(20, 60, TimeUnit.SECONDS))
.connectTimeout(3, TimeUnit.SECONDS)
.readTimeout(3, TimeUnit.SECONDS)
.build();
// 同步 GET 请求
private static void syncGet(String url) {
Request request = new Request.Builder()
.url(url)
.addHeader("Accept", "application/json")
.build();
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
System.out.println("GET 成功: " + response.body().string());
} else {
System.err.println("GET 失败: HTTP " + response.code());
}
} catch (IOException e) {
System.err.println("网络异常: " + e.getMessage());
}
}
}
若调用方是消息消费者/定时任务,推荐异步 enqueue(),但需确保回调中不阻塞,这种在安卓开发常使用。这个是通过okhttp3.Dispatcher实现,这个也可以进行调整。
java
OkHttpClient client = new OkHttpClient.Builder()
.dispatcher(new Dispatcher().apply(d -> {
d.setMaxRequests(128); // 全局最大并发(默认64)
d.setMaxRequestsPerHost(12);// 单域名最大并发(默认5)
}))
.build();
java
// 异步 GET 请求(推荐用于 Android/UI 线程)
private static void asyncGet(String url) {
Request request = new Request.Builder()
.url(url)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
System.err.println("异步请求失败: " + e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
// 注意:回调线程非主线程,Android 中更新 UI 需切回主线程
try (Response res = response) { // 手动关闭,避免泄漏
if (res.isSuccessful()) {
System.out.println("异步 GET 成功: " + res.body().string());
} else {
System.err.println("异步响应异常: " + res.code());
}
}
}
});
}