簡介
HTTP是現代應用常用的一種交換數據和媒體的網絡方式,高效地使用HTTP能讓資源加載更快,節省帶寬。OkHttp是一個高效的HTTP客戶端,它有以下默認特性:
- 支持HTTP/2,允許所有同一個主機地址的請求共享同一個socket連接
- 連接池減少請求延時
- 透明的GZIP壓縮減少響應數據的大小
- 緩存響應內容,避免一些完全重復的請求
源碼:https://github.com/square/okhttp
說明:OkHttp支持Android 2.3及以上版本Android平台,對於Java, JDK1.7及以上。
當網絡出現問題的時候OkHttp依然堅守自己的職責,它會自動恢復一般的連接問題,如果你的服務有多個IP地址,當第一個IP請求失敗時,OkHttp會交替嘗試你配置的其他IP,OkHttp使用現代TLS技術(SNI, ALPN)初始化新的連接,當握手失敗時會回退到TLS 1.0。
簡單使用
引入maven依賴
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.0.0-RC1</version>
</dependency>
請求方法
同步請求
就是執行請求的操作是阻塞式,直到 HTTP 響應返回。它對應 OKHTTP 中的 execute 方法。
GET請求
/**
* 同步get方式請求
*
* @param url
* @return
* @throws IOException
*/
public static String doGet(String url) throws IOException {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
return response.body().string();
} else {
throw new IOException("Unexpected code " + response);
}
}
}
POST請求
Json提交參數
/**
* 同步post方式請求-json提交參數
*
* @param url
* @param json
* @return
* @throws IOException
*/
public static String doPost(String url, final String json) throws IOException {
OkHttpClient client = new OkHttpClient();
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
return response.body().string();
} else {
throw new IOException("Unexpected code " + response);
}
}
}
form表單提交參數
/**
* 同步post方式請求-form表單提交參數
*
* @param url
* @param paramsMap
* @return
* @throws IOException
*/
public static String doPost(String url, Map<String, String> paramsMap) throws IOException {
OkHttpClient client = new OkHttpClient();
FormBody.Builder builder = new FormBody.Builder();
for (String key : paramsMap.keySet()) {
builder.add(key, paramsMap.get(key));
}
RequestBody formBody = builder.build();
Request request = new Request.Builder()
.url(url)
.post(formBody)
.build();
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
return response.body().string();
} else {
throw new IOException("Unexpected code " + response);
}
}
}
異步請求
就是類似於非阻塞式的請求,它的執行結果一般都是通過接口回調的方式告知調用者。它對應 OKHTTP 中的 enqueue 方法。
這是異步請求,所以調用enqueue則無需再開啟子線程,enqueue方法會自動將網絡請求部分放入子線程中執行。enqueue回調方法onResponse與onFailure都執行在子線程中。
注意事項:
-
- 回調接口的onFailure方法和onResponse執行在子線程。
-
- Response.code是http響應行中的code,如果訪問成功則返回200.這個不是服務器設置的,而是http協議中自帶的。res中的code才是服務器設置的。注意二者的區別。
-
- response.body().string()本質是輸入流的讀操作,所以它還是網絡請求的一部分,所以這行代碼必須放在子線程。
-
- response.body().string()只能調用一次,在第一次時有返回值,第二次再調用時將會返回null。原因是:response.body().string()的本質是輸入流的讀操作,必須有服務器的輸出流的寫操作時客戶端的讀操作才能得到數據。而服務器的寫操作只執行一次,所以客戶端的讀操作也只能執行一次,第二次將返回null。
-
- 再次強調,response.body().string()方法必須放在子線程中。當執行這行代碼得到結果后,再跳轉到UI線程修改UI。
異步請求自定義回調函數
/**
* okhttp 異步調用回調函數
*/
static class OkHttpCallback implements Callback {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
log.error(e);
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
if (response.isSuccessful()) {
log.info("Successful data acquisition . . . ");
log.info("response.code()==" + response.code());
log.info("response.body().string()==" + response.body().string());
}
}
}
GET請求
/**
* 異步get方式請求
*
* @param url
* @return
* @throws IOException
*/
public static void doSyncGet(String url) {
OkHttpClient okHttpClient = new OkHttpClient();
final Request request = new Request.Builder()
.url(url)
.get()
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new OkHttpCallback());
}
POST請求
Json提交參數
/**
* 異步post方式請求-json提交參數
*
* @param url
* @param json
* @return
* @throws IOException
*/
public static void doSyncPost(String url, final String json) {
OkHttpClient client = new OkHttpClient();
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
client.newCall(request).enqueue(new OkHttpCallback());
}
form表單提交參數
/**
* 異步post方式請求-form表單提交參數
*
* @param url
* @param paramsMap
* @return
* @throws IOException
*/
public static void doSyncPost(String url, Map<String, String> paramsMap) {
OkHttpClient client = new OkHttpClient();
FormBody.Builder builder = new FormBody.Builder();
for (String key : paramsMap.keySet()) {
builder.add(key, paramsMap.get(key));
}
RequestBody formBody = builder.build();
Request request = new Request.Builder()
.url(url)
.post(formBody)
.build();
client.newCall(request).enqueue(new OkHttpCallback());
}
參考
示例代碼
package com.ohaotian.feifz.style.study.utils;
import lombok.extern.log4j.Log4j2;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.util.Map;
/**
* @author feifz
* @version 1.0.0
* @Description http工具類,基於okhttp3
* @createTime 2019年06月06日 09:30:00
*/
@Log4j2
public class HttpUtil {
public static final MediaType JSON = MediaType.get("application/json; charset=utf-8");
/**
* 同步get方式請求
*
* @param url
* @return
* @throws IOException
*/
public static String doGet(String url) throws IOException {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
return response.body().string();
} else {
throw new IOException("Unexpected code " + response);
}
}
}
/**
* 異步get方式請求
*
* @param url
* @return
* @throws IOException
*/
public static void doSyncGet(String url) {
OkHttpClient okHttpClient = new OkHttpClient();
final Request request = new Request.Builder()
.url(url)
.get()
.build();
Call call = okHttpClient.newCall(request);
call.enqueue(new OkHttpCallback());
}
/**
* 同步post方式請求-json提交參數
*
* @param url
* @param json
* @return
* @throws IOException
*/
public static String doPost(String url, final String json) throws IOException {
OkHttpClient client = new OkHttpClient();
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
return response.body().string();
} else {
throw new IOException("Unexpected code " + response);
}
}
}
/**
* 異步post方式請求-json提交參數
*
* @param url
* @param json
* @return
* @throws IOException
*/
public static void doSyncPost(String url, final String json) {
OkHttpClient client = new OkHttpClient();
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
client.newCall(request).enqueue(new OkHttpCallback());
}
/**
* 同步post方式請求-form表單提交參數
*
* @param url
* @param paramsMap
* @return
* @throws IOException
*/
public static String doPost(String url, Map<String, String> paramsMap) throws IOException {
OkHttpClient client = new OkHttpClient();
FormBody.Builder builder = new FormBody.Builder();
for (String key : paramsMap.keySet()) {
builder.add(key, paramsMap.get(key));
}
RequestBody formBody = builder.build();
Request request = new Request.Builder()
.url(url)
.post(formBody)
.build();
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
return response.body().string();
} else {
throw new IOException("Unexpected code " + response);
}
}
}
/**
* 異步post方式請求-form表單提交參數
*
* @param url
* @param paramsMap
* @return
* @throws IOException
*/
public static void doSyncPost(String url, Map<String, String> paramsMap) {
OkHttpClient client = new OkHttpClient();
FormBody.Builder builder = new FormBody.Builder();
for (String key : paramsMap.keySet()) {
builder.add(key, paramsMap.get(key));
}
RequestBody formBody = builder.build();
Request request = new Request.Builder()
.url(url)
.post(formBody)
.build();
client.newCall(request).enqueue(new OkHttpCallback());
}
/**
* okhttp 異步調用回調函數
*/
static class OkHttpCallback implements Callback {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
log.error(e);
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
if (response.isSuccessful()) {
log.info("Successful data acquisition . . . ");
log.info("response.code()==" + response.code());
log.info("response.body().string()==" + response.body().string());
}
}
}
}
結語
歡迎關注微信公眾號『碼仔zonE』,專注於分享Java、雲計算相關內容,包括SpringBoot、SpringCloud、微服務、Docker、Kubernetes、Python等領域相關技術干貨,期待與您相遇!

