OkHttp3
是由Square
貢獻的HTTP
客戶端框架,主要用在Andorid
中,但是由於其易用的API、強大的功能、請求的快速等特點,也被大量采用在后端開發領域。本系列文章講述OkHttp3
的基本使用、OkHttp3
的高級功能以及OkHttp3
源碼的解析等,請持續關注。
本篇文章是此系列的第一篇。
介紹
OkHttp
是一款優秀的HTTP
客戶端框架,OkHttp3
是OkHttp
發展到版本3.0
之后的名字。在maven中央倉庫搜索okhttp
,可以看到包名為com.squareup.okhttp
項目的最后版本號是2.7.5
,而3.0
版本之后,包名更改為com.squareup.okhttp3
,同時版本號從3.0.0-RC1
開始。后面為了區分,OkHttp 3.0
之后的版本統一稱為OkHttp3
。
OkHttp3
目前已更新到4.8.0
,3.X
版本的編寫語言為Java,更新到4.0
版本以后,編寫語言修改為Kotlin
(可見OkHttp3
對Android
的支持力度)。因為筆者對Kotlin
語言不是很了解,而且主要領域在后端開發,所以本系列文章都是以OkHttp3 3.X
版本的最后一個更新版本3.14.9
為基礎構建代碼、分析代碼。
其他框架
Apache HttpClient
在后端領域,出現比較早而且使用仍然很廣泛的HTTP
客戶端框架非Apache HttpClient
莫屬了,目前大量項目和公司仍在采用該框架。Apache HttpClient
有着不錯的性能、豐富的功能以及強大的自定義實現等特色。但是隨着技術的發展和設計理念的改變,Apache HttpClient
顯的有些落伍。Apache HttpClient
和OkHttp3
相比,主要的劣勢在於Apache HttpClient
的API設計過於臃腫,使用起來有諸多不便,此外Apache HttpClient
對於一些功能沒有提供原生化的支持,需要在每次使用的時候自定義(比如池化HTTP請求、空閑連接處理等),對於首次接觸的開發者就顯得不是特別友好。而OkHttp3
是一款對新手很友好的框架,簡便易懂的API以及原生封裝高級功能的特性使得用戶在進行簡單的請求時只需要編寫少量代碼即可完成功能。
下面的示例分別使用Apache HttpClient
和OkHttp3
發送POST
請求,比較兩者的代碼量和功能。
// Apache HttpClient發送POST請求
public static String doPost(String url, String params) throws Exception {
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("Content-Type", "application/json");
String charSet = "UTF-8";
StringEntity entity = new StringEntity(params, charSet);
httpPost.setEntity(entity);
CloseableHttpResponse response = null;
try {
response = httpclient.execute(httpPost);
StatusLine status = response.getStatusLine();
int state = status.getStatusCode();
if (state == HttpStatus.SC_OK) {
HttpEntity responseEntity = response.getEntity();
String jsonString = EntityUtils.toString(responseEntity);
return jsonString;
}
} finally {
if (response != null) {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return "";
}
// OkHttp3發送POST請求
public JSONObject doPost(String url, String params) throws Exception {
OkHttpClient.Builder builder = new OkHttpClient.Builder().build();
MediaType APPLICATION_JSON = MediaType.parse("application/json");
Request request = new Request.Builder()
.url(url)
.post(RequestBody.create(APPLICATION_JSON, body))
.addHeader("Content-Type", "application/json")
.build();
Response response = null;
try {
response = okHttpClient.newCall(request).execute();
} catch (Exception e) {
e.printStackTrace();
}
if (response.isSuccessful()) {
return response.body() == null ? "" : response.body().string();
}
return "";
}
Apache HttpClient
示例的代碼量明顯多於OkHttp3
,而且后者代碼的更易讀,同時后者已經默認實現連接池、重試等功能,而前者要是支持這些額外的功能則需要自定義實現。
HttpClient
JDK 11
中提供了原生的HTTP客戶端框架,位於包java.net.http
中。HttpClient
的API設計的也簡單易懂,完成功能所需的代碼量也不是很多,而且API的設計和OkHttp3
有幾分相似。
// 使用HttpClient發送POST請求的部分代碼示例
HttpRequest request = HttpRequest.newBuilder()
.POST(HttpRequest.BodyPublishers.ofString(body))
.uri(URI.create(url))
.version(HttpClient.Version.HTTP_1_1)
.header("Content-Type", "application/json")
.build();
HttpResponse<String> response = null;
try {
response = httpClient.send(request,HttpResponse.BodyHandlers.ofString());
} catch (Exception e) {
e.printStackTrace();
}
但是由於出現的比較晚,提供的功能比較有限,比如對於multipart/form-data
的請求就很難實現。但是憑借原生的支持以及優秀的API設計,我覺得它是一個很有前途的HTTP客戶端框架。
功能特色
OkHttp3
能在目前眾多HTTP
客戶端框架中脫穎而出,並受到持續追捧,在於它提供了一些優秀的功能。
- 支持允許對同一主機的所有請求共享一個連接。
- 使用連接池降低請求延遲。
- 自動處理GZip壓縮減少流量消耗。
- 緩存請求響應,避免網絡重復請求。
- 網絡出現問題時,能夠靜默恢復。
- 對於多個IP的服務,失敗時能夠自動切換到備用地址。
- 支持現代TLS功能(TLS 1.3,ALPN,證書固定)。
- 請求/響應API具有流暢的構建器和不變性。
- 支持同步請求和異步請求。
- 支持自定義攔截器以實現更高級的功能(例如重定向、日志打印等)。
使用示例
Get請求
OkHttpClient client = new OkHttpClient();
String run(String url) throws IOException {
Request request = new Request.Builder()
.url(url)
.build();
try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
}
POST請求
public static final MediaType JSON = MediaType.get("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(json, JSON);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
return response.body().string();
}
}
小結
本篇內容介紹了OkHttp3
的來源歷史、和其他框架進行了比較、介紹了OkHttp3
特色功能並提供了OkHttp3
使用的基礎示例。下篇文章將會介紹OkHttp3
提供的MockWebServer
功能,介紹下該功能如何幫助我們完善代碼。