简介
在项目开发中,与第三方系统进行HTTP接口对接是常有的事,虽然Spring提供了 RestTemplate 可以使用,但在实际上手之后明显感觉 性能 和 上手难易度 差强人意。所以在这里将 OkHttp3
这个网络请求库 推荐给大家。
OkHttp 是 Square 公司基于 Java 和 Android 程序,封装的一个高性能的、轻量级的 HTTP 网络请求客户端,并且对外开源,被广泛应用于Android、Java和Kotlin语言的应用程序中。相比传统的HttpURLConnection,OkHttp3 更加高效、简单易用、功能丰富。
特点:
- 能够高效的执行 http,数据加载速度更快,更省流量
- 支持HTTP/2(有效使用套接字)
- 连接池(在没有HTTP/2的情况下减少请求延迟)
- 支持 GZIP 压缩,提升速度,节省流量
- 缓存响应数据,避免了重复的网络请求
- 从常见的连接问题中无声恢复
- 支持现代TLS功能(TLS 1.3,ALPN,证书钉子)
- 使用简单,支持同步阻塞调用和带回调的异步调用
安装
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>
使用
1、Get请求 同步
-
阻塞性质:
同步请求会阻塞调用线程,直到请求完成(成功或失败)。这意味着在请求完成之前,调用线程无法执行其他任务。 -
简单性:
同步请求的代码实现通常更直观和简单,因为它直接返回响应或抛出异常。 -
资源消耗:
由于阻塞性质,同步请求可能会消耗更多的系统资源,特别是在高并发场景下,因为它们会占用更多的线程。
public static void getSync() {
String url = "https://httpbin.org/get?name=wtt&age=23";
// 1、 初始化 客户端
OkHttpClient client = new OkHttpClient();
// 2、 构建 请求报文
Request request = new Request.Builder()
.url(url)
.get() //默认为GET请求,可以不写
.build();
// 3、 将 请求报文 交给 客户端
Call call = client.newCall(request);
// 4、 发送请求
try (Response response = call.execute()) {
// 打印 响应状态码
System.out.println(response.code());
// 打印 响应头
System.out.println(response.headers());
// 打印 响应体
System.out.println(response.body().string());
} catch (Exception e) {
e.printStackTrace();
}
}
2、Get请求 异步
-
非阻塞性质:
异步请求不会阻塞调用线程。当请求被发起后,调用线程可以继续执行其他任务,而不需要等待请求完成。当请求完成时,结果会通过回调方法(Callback)或其他方式通知给调用者。 -
高并发
:
由于异步请求的非阻塞性质,它们更适合用于高并发场景,因为它们不会消耗大量的线程资源。 -
复杂性:
异步请求的代码实现通常比同步请求更复杂,因为需要处理回调和可能的并发问题。
public static void getAsync() {
String url = "https://httpbin.org/get?name=wtt&age=23";
// 1、 初始化 客户端
OkHttpClient client = new OkHttpClient();
// 2、 构建 请求报文
Request request = new Request.Builder()
.url(url)
.header("name", "whero")
.get() //默认为GET请求,可以不写
.build();
// 3、 将 请求报文 交给 客户端
Call call = client.newCall(request);
// 4、 发送请求
call.enqueue(new Callback() {
// 失败回调
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
System.out.println("请求失败");
}
// 成功回调
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
System.out.println("请求成功的 回调");
// 打印 响应状态码
System.out.println(response.code());
// 打印 响应头
System.out.println(response.headers());
// 打印 响应体
System.out.println(response.body().string());
}
});
}
3、Post Json 异步
public static void postJson() {
String url = "https://httpbin.org/post";
// 1、 初始化 客户端
OkHttpClient client = new OkHttpClient();
// 2、构建 请求体
MediaType mediaType = MediaType.parse("application/json; charset=utf-8");// 标明 请求体 类型
RequestBody body = RequestBody.create("{\"name\":\"wtt\",\"age\":23}", mediaType);
// 3、构建 请求报文
Request request = new Request.Builder()
.url(url)
.header("name", "whero")
.post(body) //默认为POST请求,可以不写
.build();
// 4、 将 请求报文 交给 客户端
Call call = client.newCall(request);
// 5、 发送请求
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
System.out.println("请求失败");
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
System.out.println("请求成功的 回调");
// 打印 响应状态码
System.out.println(response.code());
// 打印 响应头
System.out.println(response.headers());
// 打印 响应体
System.out.println(response.body().string());
}
});
}
4、Post Form-Data 异步
public static void postForm() {
String url = "https://httpbin.org/post";
// 1、 初始化 客户端
OkHttpClient client = new OkHttpClient();
// 2、构建 请求体
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded; charset=utf-8");
RequestBody body = RequestBody.create("name=wtt&age=23", mediaType);
// 3、构建 请求报文
Request request = new Request.Builder()
.url(url)
.header("name", "whero")
.post(body) //默认为POST请求,可以不写
.build();
// 4、 将 请求报文 交给 客户端
Call call = client.newCall(request);
// 5、 发送请求
call.enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
System.out.println("请求失败");
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
System.out.println("请求成功的 回调");
// 打印 响应状态码
System.out.println(response.code());
// 打印 响应头
System.out.println(response.headers());
// 打印 响应体
System.out.println(response.body().string());
}
});
}
5、Post File Upload 异步
public static void postFile() {
String url = "http://localhost:8080/aaa";
// 1、 初始化 客户端
OkHttpClient client = new OkHttpClient();
// 2、构建 请求体:文件
MediaType mediaType = MediaType.parse("application/octet-stream");
File file = new File("/Users/wtt/Desktop/aaa.png");
RequestBody fileBody = RequestBody.create(file, mediaType);
MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", file.getName(), fileBody);
// 构建 请求体: 键值对
MultipartBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addPart(filePart)
.addFormDataPart("name", "wtt")
.addFormDataPart("age", "23")
.build();
// 3、构建 请求报文
Request request = new Request.Builder()
.url(url)
.header("Content-Type", "multipart/form-data") // 通常不需要手动设置这个header,因为OkHttp会自动处理
.post(requestBody)
.build();
// 4、 将 请求报文 交给 客户端 + 发送请求
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
System.out.println("请求失败: " + e.getMessage());
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
System.out.println("请求成功的 回调");
// 打印 响应状态码
System.out.println(response.code());
// 打印 响应头
System.out.println(response.headers());
// 打印 响应体
System.out.println(response.body().string());
}
});
}
6、Post File Download 同步
文件下载,通常是get方式请求,只需要在响应端使用字节流接受数据即可
package com.wtt;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
public class Main {
public static void main(String[] args) {
//目标存储文件
String targetFile = "./2.png";
//需要下载的原始文件
String url = "https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png";
OkHttpClient client = new OkHttpClient();
// 配置GET请求
Request request = new Request.Builder()
.url(url)
.build();
// 发起同步请求
try (Response response = client.newCall(request).execute()) {
// 获取文件字节流
byte[] stream = response.body().bytes();
// 写入目标文件
Path path = Paths.get(targetFile);
Files.write(path, stream, StandardOpenOption.CREATE);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(targetFile + "下载完成!");
}
}
7、自定义添加 请求头
......
OkHttpClient client = new OkHttpClient();
// 配置 header 头部请求参数
Headers headers = new Headers.Builder()
.add("token", "1111")
.build();
Request request = new Request.Builder()
.url(url)
.headers(headers) // 自定义添加 请求头
.post(body)
.build();
......