OkHttp3系列(一)初识OkHttp3
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
功能,介绍下该功能如何帮助我们完善代码。