Java使用okhttp3發(fā)送請求的實現(xiàn)示例
一、OkHttp3 簡介
OkHttp3 是一個高效的 HTTP 客戶端,由 Square 公司開發(fā),具有以下核心特點:
- 連接池 - 減少請求延遲,支持HTTP/2和SPDY
- 透明GZIP壓縮 - 自動壓縮請求體,減少數(shù)據(jù)傳輸量
- 響應緩存 - 避免重復網(wǎng)絡請求
- 自動重試 - 處理瞬時故障和網(wǎng)絡問題
- 異步/同步支持 - 靈活的調(diào)用方式
二、使用示例
準備工作
引入依賴:
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>創(chuàng)建OkHttpClient實例
import okhttp3.*;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
public class OkHttpExample {
// 創(chuàng)建全局OkHttpClient實例
private static final OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.addInterceptor(new LoggingInterceptor()) // 添加日志攔截器
.build();
// 簡單的日志攔截器
static class LoggingInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
long startTime = System.nanoTime();
System.out.println(String.format("Sending request %s on %s%n%s",
request.url(), chain.connection(), request.headers()));
Response response = chain.proceed(request);
long endTime = System.nanoTime();
System.out.println(String.format("Received response for %s in %.1fms%n%s",
response.request().url(), (endTime - startTime) / 1e6d, response.headers()));
return response;
}
}
}1.發(fā)送GET請求
下面的示例涵蓋普通get請求,帶查詢參數(shù)的get請求和帶請求頭的get請求。
public class GetRequestExample {
public static void basicGetRequest() throws IOException {
String url = "https://jsonplaceholder.typicode.com/posts/1";
Request request = new Request.Builder()
.url(url)
.get() // 顯式聲明GET方法,可選
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Unexpected code: " + response);
}
String responseBody = response.body().string();
System.out.println("Response: " + responseBody);
}
}
// 帶查詢參數(shù)的GET請求
public static void getWithQueryParams() throws IOException {
HttpUrl url = HttpUrl.parse("https://jsonplaceholder.typicode.com/posts")
.newBuilder()
.addQueryParameter("userId", "1")
.addQueryParameter("_limit", "5")
.build();
Request request = new Request.Builder()
.url(url)
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println("Response: " + response.body().string());
}
}
// 帶請求頭的GET請求
public static void getWithHeaders() throws IOException {
Request request = new Request.Builder()
.url("https://api.github.com/users/octocat")
.addHeader("User-Agent", "OkHttp-Example")
.addHeader("Accept", "application/vnd.github.v3+json")
.addHeader("Authorization", "Bearer your-token-here")
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println("Response: " + response.body().string());
}
}
}2. 發(fā)送POST請求
下面的示例涵蓋,發(fā)送json數(shù)據(jù),表單數(shù)據(jù)和文件上傳的post請求
public class PostRequestExample {
// POST JSON數(shù)據(jù)
public static void postJson() throws IOException {
String json = "{\"title\":\"foo\",\"body\":\"bar\",\"userId\":1}";
RequestBody body = RequestBody.create(
json,
MediaType.parse("application/json; charset=utf-8")
);
Request request = new Request.Builder()
.url("https://jsonplaceholder.typicode.com/posts")
.post(body)
.addHeader("Content-Type", "application/json")
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println("Response: " + response.body().string());
}
}
// 發(fā)送表單數(shù)據(jù)
public static void postForm() throws IOException {
RequestBody formBody = new FormBody.Builder()
.add("username", "john_doe")
.add("password", "secret123")
.add("grant_type", "password")
.build();
Request request = new Request.Builder()
.url("https://httpbin.org/post")
.post(formBody)
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println("Response: " + response.body().string());
}
}
// 發(fā)送multipart表單(文件上傳)
public static void postMultipart() throws IOException {
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("title", "My File")
.addFormDataPart("file", "filename.txt",
RequestBody.create("file content", MediaType.parse("text/plain")))
.addFormDataPart("image", "image.jpg",
RequestBody.create(new byte[]{/* 圖片數(shù)據(jù) */}, MediaType.parse("image/jpeg")))
.build();
Request request = new Request.Builder()
.url("https://httpbin.org/post")
.post(requestBody)
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println("Response: " + response.body().string());
}
}
}3.發(fā)送PUT請求
public static void putRequest() throws IOException {
String json = "{\"id\":1,\"title\":\"updated title\",\"body\":\"updated body\",\"userId\":1}";
RequestBody body = RequestBody.create(
json,
MediaType.parse("application/json; charset=utf-8")
);
Request request = new Request.Builder()
.url("https://jsonplaceholder.typicode.com/posts/1")
.put(body)
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println("PUT Response: " + response.body().string());
}
}4.發(fā)送PATCH請求
PATCH 請求用于對資源進行部分更新,與 PUT(全量更新)不同,PATCH 只更新提供的字段。
public static void patchRequest() throws IOException {
String json = "{\"title\":\"patched title\"}";
RequestBody body = RequestBody.create(
json,
MediaType.parse("application/json; charset=utf-8")
);
Request request = new Request.Builder()
.url("https://jsonplaceholder.typicode.com/posts/1")
.patch(body)
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println("PATCH Response: " + response.body().string());
}
}5.發(fā)送DELETE請求
public static void deleteRequest() throws IOException {
Request request = new Request.Builder()
.url("https://jsonplaceholder.typicode.com/posts/1")
.delete()
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println("DELETE Response: " + response.body().string());
}
}6.發(fā)送異步請求
public class AsyncRequestExample {
public static void asyncGetRequest() {
Request request = new Request.Builder()
.url("https://jsonplaceholder.typicode.com/posts/1")
.build();
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 {
if (!response.isSuccessful()) {
throw new IOException("Unexpected code: " + response);
}
String responseBody = response.body().string();
System.out.println("Async Response: " + responseBody);
// 注意:在異步回調(diào)中需要手動關閉response body
response.close();
}
});
System.out.println("Request sent asynchronously...");
}
// 多個異步請求并行執(zhí)行
public static void multipleAsyncRequests() {
String[] urls = {
"https://jsonplaceholder.typicode.com/posts/1",
"https://jsonplaceholder.typicode.com/posts/2",
"https://jsonplaceholder.typicode.com/posts/3"
};
for (String url : urls) {
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("Request failed: " + e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
System.out.println("Response from " + call.request().url() + ": " +
response.body().string().substring(0, 50) + "...");
}
response.close();
}
});
}
}
}7.高級功能和配置
涵蓋:添加認證token、重試攔截器、下載文件和使用Cookie
public class AdvancedFeatures {
// 自定義配置的Client
private static final OkHttpClient customClient = new OkHttpClient.Builder()
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.addInterceptor(chain -> {
// 添加認證token
Request original = chain.request();
Request authenticated = original.newBuilder()
.header("Authorization", "Bearer " + getAuthToken())
.build();
return chain.proceed(authenticated);
})
.addInterceptor(chain -> {
// 重試攔截器
int maxRetries = 3;
int retryCount = 0;
Response response = null;
while (retryCount < maxRetries) {
try {
response = chain.proceed(chain.request());
if (response.isSuccessful() || retryCount == maxRetries - 1) {
break;
}
} catch (IOException e) {
if (retryCount == maxRetries - 1) {
throw e;
}
}
retryCount++;
System.out.println("Retrying request, attempt: " + (retryCount + 1));
}
return response;
})
.build();
private static String getAuthToken() {
return "your-auth-token";
}
// 下載文件
public static void downloadFile() throws IOException {
Request request = new Request.Builder()
.url("https://httpbin.org/image/jpeg")
.build();
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
byte[] fileData = response.body().bytes();
// 保存文件到本地
// Files.write(Paths.get("image.jpg"), fileData);
System.out.println("File downloaded, size: " + fileData.length + " bytes");
}
}
}
// 使用Cookie
public static void withCookieJar() {
CookieJar cookieJar = new CookieJar() {
private final List<Cookie> cookies = new ArrayList<>();
@Override
public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
this.cookies.addAll(cookies);
}
@Override
public List<Cookie> loadForRequest(HttpUrl url) {
return cookies;
}
};
OkHttpClient clientWithCookies = new OkHttpClient.Builder()
.cookieJar(cookieJar)
.build();
}
}8.OkHttp工具類
簡單Mini版的使用示例
public class OkHttpUtils {
private static final OkHttpClient client = new OkHttpClient();
public static String doGet(String url) throws IOException {
Request request = new Request.Builder().url(url).build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Request failed: " + response);
}
return response.body().string();
}
}
public static String doPost(String url, String json) throws IOException {
RequestBody body = RequestBody.create(
json,
MediaType.parse("application/json; charset=utf-8")
);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Request failed: " + response);
}
return response.body().string();
}
}
// 使用示例
public static void main(String[] args) {
try {
// GET請求
String getResponse = doGet("https://jsonplaceholder.typicode.com/posts/1");
System.out.println("GET Response: " + getResponse);
// POST請求
String json = "{\"title\":\"test\",\"body\":\"content\",\"userId\":1}";
String postResponse = doPost("https://jsonplaceholder.typicode.com/posts", json);
System.out.println("POST Response: " + postResponse);
} catch (IOException e) {
e.printStackTrace();
}
}
}三、適用場景
- 移動應用開發(fā);
- 微服務間的HTTP通信;
- 文件上傳下載;
- 需要精細控制HTTP請求的場景;
- Web爬蟲和數(shù)據(jù)采集。
四、性能優(yōu)勢場景
高并發(fā)請求
// 連接池復用,適合高并發(fā)
for (int i = 0; i < 1000; i++) {
Request request = new Request.Builder()
.url("http://api.example.com/items/" + i)
.build();
client.newCall(request).enqueue(callback); // 連接復用
}五、注意事項
同步請求:使用 execute() 方法,會阻塞當前線程
異步請求:使用 enqueue() 方法,不會阻塞當前線程
請求構建:使用 Request.Builder 構建請求
響應處理:注意需要手動關閉Response body
連接池:OkHttp自動管理連接池,提高性能
攔截器:可以添加各種攔截器實現(xiàn)日志、認證、重試等功能
六、與其他HTTP客戶端對比
| 場景 | 推薦工具 | 理由 |
|---|---|---|
| Android應用 | OkHttp3 | 官方推薦,性能優(yōu)化 |
| Spring Boot微服務 | OpenFeign | 聲明式,集成性好 |
| 簡單Java應用 | OkHttp3 | 輕量,易用 |
| 高并發(fā)爬蟲 | OkHttp3 | 連接池,異步支持 |
| 需要精細控制 | OkHttp3 | 攔截器,自定義配置 |
到此這篇關于Java使用okhttp3發(fā)送請求的實現(xiàn)示例的文章就介紹到這了,更多相關Java okhttp3發(fā)送請求內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
使用Java將DOCX文檔解析為Markdown文檔的代碼實現(xiàn)
在現(xiàn)代文檔處理中,Markdown(MD)因其簡潔的語法和良好的可讀性,逐漸成為開發(fā)者、技術寫作者和內(nèi)容創(chuàng)作者的首選格式,然而,許多文檔仍然以Microsoft Word的DOCX格式保存,本文將介紹如何使用Java和相關庫將DOCX文檔解析為Markdown文檔,需要的朋友可以參考下2025-04-04
SpringCloud?openfeign聲明式服務調(diào)用實現(xiàn)方法介紹
在springcloud中,openfeign是取代了feign作為負載均衡組件的,feign最早是netflix提供的,他是一個輕量級的支持RESTful的http服務調(diào)用框架,內(nèi)置了ribbon,而ribbon可以提供負載均衡機制,因此feign可以作為一個負載均衡的遠程服務調(diào)用框架使用2022-12-12
SpringBoot整合Dubbo框架,實現(xiàn)RPC服務遠程調(diào)用
Dubbo是一款高性能、輕量級的開源Java RPC框架,它提供了三大核心能力:面向接口的遠程方法調(diào)用,智能容錯和負載均衡,以及服務自動注冊和發(fā)現(xiàn)。今天就來看下SpringBoot整合Dubbo框架的步驟2021-06-06
Spring ApplicationListener的使用詳解
這篇文章主要介紹了Spring ApplicationListener的使用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-06-06
一文帶你掌握SpringBoot中常見定時任務的實現(xiàn)
這篇文章主要為大家詳細介紹了Spring?Boot中定時任務的基本用法、高級特性以及最佳實踐,幫助開發(fā)人員更好地理解和應用定時任務,提高系統(tǒng)的穩(wěn)定性和可靠性,需要的可以參考下2024-03-03

