OkHttp是一个高效的HTTP请求客户端对于Android和Java应用。其有着许多高级的功能,比如线程池、GZip压缩和响应缓存。 同时不仅能够发送同步的请求,也能够支持异步调用。
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.9.1</version>
</dependency>
同步请求
我们需要基于URL地址来构建一个Reqeust对象,然后调用newCall()来生成一个Call对象,然后调用execute()方法来同步发送请求并获取相应结果
@Test
public void whenGetRequest_thenCorrect() throws IOException {
Request request = new Request.Builder()
.url(BASE_URL + "/date")
.build();
Call call = client.newCall(request);
Response response = call.execute();
assertThat(response.code(), equalTo(200));
}
异步请求
@Test
public void whenAsynchronousGetRequest_thenCorrect() {
Request request = new Request.Builder()
.url(BASE_URL + "/date")
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
public void onResponse(Call call, Response response)
throws IOException {
// ...
}
public void onFailure(Call call, IOException e) {
fail();
}
});
}
添加请求参数
@Test
public void whenGetRequestWithQueryParameter_thenCorrect()
throws IOException {
HttpUrl.Builder urlBuilder
= HttpUrl.parse(BASE_URL + "/users").newBuilder();
urlBuilder.addQueryParameter("name", "zhangsan");
String url = urlBuilder.build().toString();
Request request = new Request.Builder()
.url(url)
.build();
Call call = client.newCall(request);
Response response = call.execute();
assertThat(response.code(), equalTo(200));
}
添加请求体
表单请求
通过FormBody我们能够构造出表单请求(application/x-www-form-urlencoded),使用方式如下:
@Test
public void whenPostRequestWithBody_thenCorrect()
throws IOException {
RequestBody formBody = new FormBody.Builder()
.add("username", "test")
.add("password", "test")
.build();
Request request = new Request.Builder()
.url(BASE_URL + "/users")
.post(formBody)
.build();
Call call = client.newCall(request);
Response response = call.execute();
assertThat(response.code(), equalTo(200));
}
JSON请求
为了适应目前RESTAfulAPI风格的JSON请求格式,OkHttp提供了String类型的json支持,我们可以通过一些json序列化库来帮助我们将一些实体类型转化为json后发送请求:
private MediaType JSON_TYPE = MediaType.get("application/json; charset=utf-8");
@Test
public void whenPostRequestWithJSON_thenCorrect()
throws IOException {
User user = new User().userId(1L).username("yaowenbin");
String json = JSON.toJSONString(user);
RequestBody requestBody = RequestBody.create(JSON_TYPE, json);
Request request = new Request.Builder()
.url(BASE_URL + "/users")
.post(formBody)
.build();
Call call = client.newCall(request);
Response response = call.execute();
assertThat(response.code(), equalTo(200));
}
PUT/DELETE请求
PUT/DELETE和POST请求也类似,只不过把Request调用的post方法转化成了对应的put()和delete()罢了
@Test
public void whenPuttRequestWithBody_thenCorrect()
throws IOException {
...
Request request = new Request.Builder()
.put(requestBody)
.url(BASE_URL + "/users")
.build();
...
}
@Test
public void whenPuttRequestWithBody_thenCorrect()
throws IOException {
...
Request request = new Request.Builder()
.delete(requestBody)
.url(BASE_URL + "/users")
.build();
...
}
请求头
单次请求头
我们只需要在Request的Builder中使用addHeader即可在请求中添加请求头了:
@Test
public void whenSetHeader_thenCorrect() throws IOException {
Request request = new Request.Builder()
.url(SAMPLE_URL)
.addHeader("Content-Type", "application/json")
.build();
Call call = client.newCall(request);
Response response = call.execute();
response.close();
}
全局请求头
如果我们希望每一个发送的请求都能够携带上全局的请求参数,比如说登录Token时,OkHttp使用了Interceptor来帮助我们达到这样的效果:
@Test
public void whenSetDefaultHeader_thenCorrect()
throws IOException {
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(
new DefaultContentTypeInterceptor("application/json"))
.build();
Request request = new Request.Builder()
.url(SAMPLE_URL)
.build();
Call call = client.newCall(request);
Response response = call.execute();
response.close();
}
封装一个更加易用API
对于序列化工具你想要使用FastJSON2还是Jackson还是Gson都是没有问题的
import com.alibaba.fastjson.JSONObject;
import okhttp3.*;
import java.io.IOException;
/**
* @author : yaowenbin
*/
public class HttpUtil {
static OkHttpClient HTTP_CLIENT = new OkHttpClient.Builder()
.build();
public static final MediaType JSON
= MediaType.get("application/json; charset=utf-8");
public static String get(String url) {
Request request = new Request.Builder()
.get()
.url(url)
.build();
return synchronizedCall(request);
}
public static <T> T get(String url, Class<T> clz) {
return parse(get(url), clz);
}
public static String post(String url, String json) {
RequestBody requestBody = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.post(requestBody)
.url(url)
.build();
return synchronizedCall(request);
}
public static <T> T post(String url, String json, Class<T> clz) {
return parse(post(url, json), clz);
}
public static String put(String url, String json) {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.put(body)
.build();
return synchronizedCall(request);
}
public static String put(String url) {
return put(url, "");
}
public static <T> T put(String url, String json, Class<T> clz) {
return parse(put(url, json), clz);
}
public static String delete(String url, String json) {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.delete(body)
.build();
return synchronizedCall(request);
}
public static String delete(String url) {
return delete(url, "");
}
public static <T> T delete(String url, Class<T> clz) {
return parse(
delete(url, ""),
clz
);
}
public static <T> T delete(String url, String json, Class<T> clz) {
return parse(delete(url, json), clz);
}
private static String synchronizedCall(Request request) {
try ( Response response = HTTP_CLIENT.newCall(request).execute() ){
return response.body().toString();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static<T> T synchronizedCall(Request request, Class<T> clz) {
return parse(synchronizedCall(request), clz);
}
public static <T> T parse(String json, Class<T> clz) {
return JSONObject.parseObject(json, clz);
}
}