簡介
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等領域相關技術乾貨,期待與您相遇!