Java使用okhttp3發(fā)送請(qǐng)求的實(shí)現(xiàn)示例
一、OkHttp3 簡(jiǎn)介
OkHttp3 是一個(gè)高效的 HTTP 客戶端,由 Square 公司開(kāi)發(fā),具有以下核心特點(diǎn):
- 連接池 - 減少請(qǐng)求延遲,支持HTTP/2和SPDY
- 透明GZIP壓縮 - 自動(dòng)壓縮請(qǐng)求體,減少數(shù)據(jù)傳輸量
- 響應(yīng)緩存 - 避免重復(fù)網(wǎng)絡(luò)請(qǐng)求
- 自動(dòng)重試 - 處理瞬時(shí)故障和網(wǎng)絡(luò)問(wèn)題
- 異步/同步支持 - 靈活的調(diào)用方式
二、使用示例
準(zhǔn)備工作
引入依賴:
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>創(chuàng)建OkHttpClient實(shí)例
import okhttp3.*;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
public class OkHttpExample {
// 創(chuàng)建全局OkHttpClient實(shí)例
private static final OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.addInterceptor(new LoggingInterceptor()) // 添加日志攔截器
.build();
// 簡(jiǎn)單的日志攔截器
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請(qǐng)求
下面的示例涵蓋普通get請(qǐng)求,帶查詢參數(shù)的get請(qǐng)求和帶請(qǐng)求頭的get請(qǐng)求。
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請(qǐng)求
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());
}
}
// 帶請(qǐng)求頭的GET請(qǐng)求
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請(qǐng)求
下面的示例涵蓋,發(fā)送json數(shù)據(jù),表單數(shù)據(jù)和文件上傳的post請(qǐng)求
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請(qǐng)求
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請(qǐng)求
PATCH 請(qǐng)求用于對(duì)資源進(jìn)行部分更新,與 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請(qǐng)求
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ā)送異步請(qǐng)求
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)中需要手動(dòng)關(guān)閉response body
response.close();
}
});
System.out.println("Request sent asynchronously...");
}
// 多個(gè)異步請(qǐng)求并行執(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.高級(jí)功能和配置
涵蓋:添加認(rèn)證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 -> {
// 添加認(rèn)證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工具類(lèi)
簡(jiǎn)單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請(qǐng)求
String getResponse = doGet("https://jsonplaceholder.typicode.com/posts/1");
System.out.println("GET Response: " + getResponse);
// POST請(qǐng)求
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();
}
}
}三、適用場(chǎng)景
- 移動(dòng)應(yīng)用開(kāi)發(fā);
- 微服務(wù)間的HTTP通信;
- 文件上傳下載;
- 需要精細(xì)控制HTTP請(qǐng)求的場(chǎng)景;
- Web爬蟲(chóng)和數(shù)據(jù)采集。
四、性能優(yōu)勢(shì)場(chǎng)景
高并發(fā)請(qǐng)求
// 連接池復(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); // 連接復(fù)用
}五、注意事項(xiàng)
同步請(qǐng)求:使用 execute() 方法,會(huì)阻塞當(dāng)前線程
異步請(qǐng)求:使用 enqueue() 方法,不會(huì)阻塞當(dāng)前線程
請(qǐng)求構(gòu)建:使用 Request.Builder 構(gòu)建請(qǐng)求
響應(yīng)處理:注意需要手動(dòng)關(guān)閉Response body
連接池:OkHttp自動(dòng)管理連接池,提高性能
攔截器:可以添加各種攔截器實(shí)現(xiàn)日志、認(rèn)證、重試等功能
六、與其他HTTP客戶端對(duì)比
| 場(chǎng)景 | 推薦工具 | 理由 |
|---|---|---|
| Android應(yīng)用 | OkHttp3 | 官方推薦,性能優(yōu)化 |
| Spring Boot微服務(wù) | OpenFeign | 聲明式,集成性好 |
| 簡(jiǎn)單Java應(yīng)用 | OkHttp3 | 輕量,易用 |
| 高并發(fā)爬蟲(chóng) | OkHttp3 | 連接池,異步支持 |
| 需要精細(xì)控制 | OkHttp3 | 攔截器,自定義配置 |
到此這篇關(guān)于Java使用okhttp3發(fā)送請(qǐng)求的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)Java okhttp3發(fā)送請(qǐng)求內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于SpringBoot實(shí)現(xiàn)發(fā)送帶附件的郵件
這篇文章主要介紹了基于SpringBoot實(shí)現(xiàn)發(fā)送帶附件的郵件,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11
springboot實(shí)現(xiàn)發(fā)送郵件(QQ郵箱為例)
這篇文章主要為大家詳細(xì)介紹了springboot實(shí)現(xiàn)發(fā)送郵件,qq郵箱代碼實(shí)現(xiàn)郵件發(fā)送,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-06-06
java實(shí)現(xiàn)簡(jiǎn)易貪吃蛇游戲
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)易貪吃蛇游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-12-12
如何在Redis中實(shí)現(xiàn)分頁(yè)排序查詢過(guò)程解析
這篇文章主要介紹了如何在Redis中實(shí)現(xiàn)分頁(yè)排序查詢過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07
SpringBoot集成Tomcat服務(wù)架構(gòu)配置
這篇文章主要為大家介紹了SpringBoot集成Tomcat服務(wù)架構(gòu)配置,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02
Spring事件監(jiān)聽(tīng)器ApplicationListener源碼詳解
這篇文章主要介紹了Spring事件監(jiān)聽(tīng)器ApplicationListener源碼詳解,ApplicationEvent以及Listener是Spring為我們提供的一個(gè)事件監(jiān)聽(tīng)、訂閱的實(shí)現(xiàn),內(nèi)部實(shí)現(xiàn)原理是觀察者設(shè)計(jì)模式,需要的朋友可以參考下2023-05-05
Springboot重寫(xiě)addInterceptors()方法配置攔截器實(shí)例
這篇文章主要介紹了Springboot重寫(xiě)addInterceptors()方法配置攔截器實(shí)例,spring?boot拋棄了復(fù)雜的xml配置,我們可以自定義配置類(lèi)(標(biāo)注@Configuration注解的類(lèi))來(lái)實(shí)現(xiàn)WebMvcConfigurer接口,并重寫(xiě)addInterceptors()方法來(lái)配置攔截器,需要的朋友可以參考下2023-09-09
spring boot+redis 監(jiān)聽(tīng)過(guò)期Key的操作方法
這篇文章主要介紹了spring boot+redis 監(jiān)聽(tīng)過(guò)期Key,本文通過(guò)示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-08-08

