learn and grow up

java的okhttp再封装

字数统计: 1.3k阅读时长: 6 min
2019/12/07 Share

写在前面

java生态中有很多对http封装的组件,比如原生的 HttpURLConnection 或者apache的 HTTPClient、spring cloud中的RestTemplate和Feign等。

其中:

  • HttpURLConnection 和HttpClient:代码复杂,还得操心资源回收等。代码很复杂,冗余代码多,不建议直接使用。
  • RestTemplate和Feign主要是访问restful服务,其他非restful会很复杂。

所以项目中对于非restful服务,使用了okhttp,OkHttp是一款优秀的HTTP框架,它支持get请求和post请求,支持基于Http的文件上传和下载,支持加载图片,支持下载文件透明的GZIP压缩,支持响应缓存避免重复的网络请求,支持使用连接池来降低响应延迟问题。

但是原生的okhttp的api比较简单,所以我在开发过程中对它进行了简单的封装,让我们可以更加方便的调用和扩展

封装代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
@Slf4j
@Component
public class OKHttpUtil {

private static final OkHttpClient client = new OkHttpClient();

public static String get(String url, Map<String, String> headers, Map<String, Object> params) throws Exception {
return dealRequestByMethod(HttpMethod.GET, url, headers, params,false);
}

public static byte[] getByte(String url, Map<String, String> headers, Map<String, Object> params) throws Exception {
Call call=getCall(HttpMethod.GET, url, headers,
params, false);
try (Response response = call.execute()) {
return response.body().bytes();
} catch (Exception e) {
log.error("远程接口请求失败![url:{}][headers:{}][params:{}][reason:{}]",
url, JSON.toJSONString(headers), JSON.toJSONString(params), e);
throw new Exception("远程服务暂时不可用, 请稍后重试!", e);
}
}

public static <T> T getEntity(
String url, Map<String, String> headers,
Map<String, Object> params, Class<T> clazz) throws Exception {
String resultStr = dealRequestByMethod(HttpMethod.GET, url, headers, params,false);
T obj = JSON.parseObject(resultStr, clazz);
return obj;
}

public static <T> T postEntity(
String url, Map<String, String> headers,
Map<String, Object> params, Class<T> clazz) throws Exception {
String resultStr = dealRequestByMethod(HttpMethod.POST, url, headers, params,false);
T obj = JSON.parseObject(resultStr, clazz);
return obj;
}

public static String post(String url, Map<String, String> headers, Map<String, Object> params) throws Exception {
return dealRequestByMethod(HttpMethod.POST, url, headers, params,false);
}

/**
* 以 application/x-www-form-urlencoded 发送 post 请求(默认application/json)
*/
public static <T> T postWithFormUrlencodedEntity(
String url, Map<String, String> headers,
Map<String, Object> params, Class<T> clazz) throws Exception {
String resultStr = dealRequestByMethod(HttpMethod.POST, url, headers, params, true);
T obj = JSON.parseObject(resultStr, clazz);
return obj;
}

/**
* 通过处理方法分发处理请求
*/
private static String dealRequestByMethod(HttpMethod httpMethod, String url, Map<String, String> headers,
Map<String, Object> params, Boolean isFormUrlencode) throws Exception {
Call call=getCall(httpMethod, url, headers,
params, isFormUrlencode);
//异步请求结果(请求加入调度)
// asyncReturnResult(url, headers, params, call);
//同步调用处理
try (Response response = call.execute()) {
return response.body().string();
} catch (Exception e) {
log.error("远程接口请求失败![url:{}][headers:{}][params:{}][reason:{}]",
url, JSON.toJSONString(headers), JSON.toJSONString(params), e);
throw new Exception("远程服务暂时不可用, 请稍后重试!", e);
}
}

private static void dealRequestByMethodWithCallback(HttpMethod httpMethod, String url, Map<String, String> headers,
Map<String, Object> params, Boolean isFormUrlencode,Callback callback) throws Exception {
Call call=getCall(httpMethod, url, headers,
params, isFormUrlencode);
syncReturnResult(url, headers, params, call,callback);
}

private static Call getCall(HttpMethod httpMethod, String url, Map<String, String> headers,
Map<String, Object> params, Boolean isFormUrlencode) throws Exception {
Request.Builder requestBuilder = new Request.Builder();
//添加请求头
addHeaders(headers, requestBuilder);
switch (httpMethod) {
case GET:
default:
addGetParams(url, params, requestBuilder);
break;
case POST:
addPostParams(url, params, requestBuilder, isFormUrlencode);
break;
}
Request request = requestBuilder.build();
Call call = client.newCall(request);
//异步请求结果(请求加入调度)
// asyncReturnResult(url, headers, params, call);
//同步调用处理
return call;
}

public static final MediaType JSON_CHARSET = MediaType.get("application/json; charset=utf-8");


private static void syncReturnResult(String url, Map<String, String> headers, Map<String, Object> params, Call call,Callback callback) throws Exception {

try {
call.enqueue(callback);
} catch (Exception e) {
log.error("远程接口请求失败![url:{}][headers:{}][params:{}][reason:{}]",
url, JSON.toJSONString(headers), JSON.toJSONString(params), e);
throw new Exception("远程服务暂时不可用, 请稍后重试!", e);
}
}
/**
* 添加 get参数
*/
private static void addGetParams(String url, Map<String, Object> params, Request.Builder requestBuilder) {
StringBuilder paramUrl = new StringBuilder(url);
if (params != null && params.size() > 0) {
paramUrl.append("?");
params.forEach((k, v) -> paramUrl.append(k + "=" + v + "&"));
paramUrl.deleteCharAt(paramUrl.length() - 1);
}
requestBuilder.url(paramUrl.toString());
}

/**
* 添加 post 参数
*/
private static void addPostParams(String url, Map<String, Object> params,
Request.Builder requestBuilder, Boolean isFormUrlencode) {
RequestBody requestBody;
if (params != null && params.size() > 0) {
// post form 方式发送的为如下
if (isFormUrlencode) {
Builder builder = new Builder();
params.forEach((k, v) -> builder.addEncoded(k, v.toString()));
requestBody = builder.build();
} else {
// 默认 json 发送
log.info("json:" + JSON.toJSONString(params));
requestBody = RequestBody.create(JSON_CHARSET, JSON.toJSONString(params));
}
} else {
requestBody = RequestBody.create(JSON_CHARSET, "{}");
}
requestBuilder.post(requestBody);
requestBuilder.url(url);
}

/**
* 添加请求头
*
* @param headers
* @param requestBuilder
*/
private static void addHeaders(Map<String, String> headers, Request.Builder requestBuilder) {
if (headers == null) {
headers = new HashMap<>(4);
}
// if (!headers.containsKey("Content-Type")) {
// headers.put("Content-Type", "application/json;charset=UTF-8");
// }
headers.forEach((k, v) -> requestBuilder.addHeader(k, v));
}

/**
* post请求,异步方式,提交数据,是在子线程中执行的,需要切换到主线程才能更新UI
*
* @param url
* @param bodyParams
* @param myNetCall
*/
// public void postDataAsynToNet(String url, Map<String, String> bodyParams, final MyNetCall myNetCall) {
// //1构造RequestBody
// RequestBody body = setRequestBody(bodyParams);
// //2 构造Request
// Request.Builder requestBuilder = new Request.Builder();
// Request request = requestBuilder.post(body).url(url).build();
// //3 将Request封装为Call
// Call call = mOkHttpClient.newCall(request);
// //4 执行Call
// call.enqueue(new Callback() {
// @Override
// public void onFailure(Call call, IOException e) {
// myNetCall.failed(call, e);
// }
//
// @Override
// public void onResponse(Call call, Response response) throws IOException {
// myNetCall.success(call, response);
//
// }
// });
// }

}
CATALOG
  1. 1. 写在前面
  2. 2. 封装代码