OkHttp学习
# OkHttp 简介与使用示例
OkHttp 是一个高效的 HTTP 客户端,用于 Android、Java 应用程序以及 Kotlin 应用程序。它支持同步阻塞调用和异步调用,同时提供了强大的拦截器和重定向处理功能。OkHttp 由 Square 公司开发,因其高性能和易用性而广受欢迎。
# 为什么选择 OkHttp?
- 性能:OkHttp 经过精心设计,以最小化网络延迟和数据使用量。
- 简洁性:OkHttp 的 API 设计简洁直观,易于上手。
- 可扩展性:OkHttp 支持自定义配置和拦截器,可以灵活地适应不同的需求。
- 兼容性:OkHttp 支持 HTTP/2 和 WebSocket,适用于现代网络通信。
# 快速开始
首先,您需要在项目的 pom.xml
文件中添加 OkHttp 的依赖:
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>
1
2
3
4
5
2
3
4
5
# 同步 GET 请求
以下是一个简单的同步 GET 请求示例:
OkHttpClient client = new OkHttpClient();
String url = "https://api.example.com/data";
Request request = new Request.Builder()
.url(url)
.build();
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
String responseData = response.body().string();
// 处理响应数据
} else {
// 处理错误响应
}
} catch (IOException e) {
// 处理网络异常
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 异步 GET 请求
对于不需要立即返回结果的场景,可以使用异步请求:
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
// 网络请求失败
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
String responseData = response.body().string();
// 异步处理响应数据
} else {
// 异步处理错误响应
}
}
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# POST 请求
发送 POST 请求并附带请求体:
String url = "https://api.example.com/submit";
String json = "{\"name\":\"John\",\"age\":30}";
RequestBody body = RequestBody.create(json, MediaType.get("application/json; charset=utf-8"));
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
// 网络请求失败
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
// 请求成功
} else {
// 处理错误响应
}
}
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 上传文件
OkHttp 也支持文件上传:
String url = "https://api.example.com/upload";
File file = new File("/sdcard/image.png");
RequestBody fileBody = RequestBody.create(MediaType.parse("image/png"), file);
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", file.getName(), fileBody)
.build();
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
client.newCall(request).enqueue(new Callback() {
// ...
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 配置和拦截器
OkHttp 允许您配置连接参数和添加拦截器:
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.addInterceptor(new LoggingInterceptor())
.build();
1
2
3
4
5
6
2
3
4
5
6
# 工具类
/**
* @author chenmeng
*/
@SuppressWarnings("all")
public class OkHttpUtil {
private static final Logger logger = LoggerFactory.getLogger("okHttpReq");
private static final long DEFAULT_TIMEOUT = 5000;
private static final int MAX_IDLE_CONNECTION = 5;
private static final long KEEP_ALIVE_DURATION = 1;
public static final String JSON_CONTENT_TYPE = "application/json; charset=utf-8";
public static final String FORM_CONTENT_TYPE = "application/x-www-form-urlencoded";
private OkHttpUtil() {
// 单例模式,防止外部实例化
}
private static final OkHttpClient HTTP_CLIENT = new OkHttpClient.Builder()
.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS)
.readTimeout(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS)
.writeTimeout(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS)
.callTimeout(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS)
.connectionPool(new ConnectionPool(MAX_IDLE_CONNECTION, KEEP_ALIVE_DURATION, TimeUnit.MINUTES))
.build();
/**
* 发送GET请求
*
* @param url 请求URL
* @return 响应结果字符串
*/
public static String sendGet(String url) {
return sendGetWithHeaders(url, null, null);
}
/**
* 携带参数发送GET请求
*
* @param url 请求URL
* @param param 请求参数
* @return 响应结果字符串
*/
public static String sendGetWithParam(String url, String param) {
return sendGetWithHeaders(url, param, null);
}
/**
* 携带请求头发送GET请求
*
* @param url 请求URL
* @param param 请求参数
* @param headers 请求头(可选)
* @return 响应结果字符串
*/
public static String sendGetWithHeaders(String url, String param, Map<String, String> headers) {
String realUrl = url;
if (StrUtil.isNotBlank(param)) {
realUrl = url + "?" + param;
}
Request.Builder builder = new Request.Builder()
.url(realUrl)
.header("accept", "*/*")
.header("connection", "Keep-Alive")
.get();
if (headers != null) {
for (Map.Entry<String, String> entry : headers.entrySet()) {
builder.addHeader(entry.getKey(), entry.getValue());
}
}
Request request = builder.build();
try (Response response = HTTP_CLIENT.newCall(request).execute()) {
if (response.isSuccessful()) {
// 处理响应数据
long time = response.receivedResponseAtMillis() - response.sentRequestAtMillis();
String result = response.body() != null ? response.body().string() : null;
printRequestLog(url, null, param, time, result);
return result;
} else {
// 处理错误响应
// return response.toString();
throw new IOException(String.valueOf(response));
}
} catch (Exception e) {
// 处理网络异常
logger.error("invoke Remote 【GET】 Method exception!== url【{}】,param【{}】", url, param);
return returnErrorResult("远程请求失败:" + e.getMessage()).toString();
}
}
/**
* 发送POST请求(application/json; charset=utf-8)
*
* @param url 请求URL
* @param param JSON字符串请求体
* @return 响应结果字符串
*/
public static String sendPostJson(String url, String param) {
return sendPostJsonWithHeaders(url, param, null);
}
/**
* 携带请求头发送POST请求(application/json)
*
* @param url 请求URL
* @param param JSON字符串请求体
* @param headers 请求头(可选)
* @return 响应结果字符串
*/
public static String sendPostJsonWithHeaders(String url, String param, Map<String, String> headers) {
MediaType mediaType = MediaType.parse(JSON_CONTENT_TYPE);
RequestBody requestBody = RequestBody.create(param, mediaType);
Request.Builder builder = new Request.Builder()
.url(url)
.header("accept", "*/*")
.header("connection", "Keep-Alive")
.header("Content-Type", JSON_CONTENT_TYPE)
.post(requestBody);
if (headers != null) {
for (Map.Entry<String, String> entry : headers.entrySet()) {
builder.addHeader(entry.getKey(), entry.getValue());
}
}
Request request = builder.build();
try (Response response = HTTP_CLIENT.newCall(request).execute()) {
if (response.isSuccessful()) {
// 处理响应数据
long time = response.receivedResponseAtMillis() - response.sentRequestAtMillis();
String result = response.body() != null ? response.body().string() : null;
printRequestLog(url, JSON_CONTENT_TYPE, param, time, result);
return result;
} else {
// 处理错误响应
throw new IOException(String.valueOf(response));
}
} catch (Exception e) {
// 处理网络异常
logger.error("invoke Remote 【POST】 Method exception!== url【{}】,param【{}】", url, param, e);
return returnErrorResult("Remote Request Fail--" + e.getMessage()).toString();
}
}
/**
* 发送POST请求(application/x-www-form-urlencoded)
*
* @param url 请求URL
* @param params 请求参数(可选)
* @return 响应结果字符串
*/
public static String sendPostForm(String url, Map<String, Object> params) {
return sendPostFormWithHeaders(url, params, null);
}
/**
* 携带请求头发送POST请求(application/x-www-form-urlencoded)
*
* @param url 请求URL
* @param params 请求参数(可选)
* @param headers 请求头(可选)
* @return 响应结果字符串
*/
public static String sendPostFormWithHeaders(String url, Map<String, Object> params,
Map<String, String> headers) {
RequestBody formBody;
StringBuilder strParamsBuilder = new StringBuilder();
if (params != null && !params.isEmpty()) {
FormBody.Builder formBuilder = new FormBody.Builder();
for (Map.Entry<String, Object> entry : params.entrySet()) {
formBuilder.add(entry.getKey(), entry.getValue().toString());
}
formBody = formBuilder.build();
// 打印参数
for (Map.Entry<String, Object> e : params.entrySet()) {
strParamsBuilder.append(e.getKey()).append("=").append(e.getValue()).append("&");
}
} else {
// 若无参数,创建一个空的FormBody
formBody = new FormBody.Builder().build();
}
String strParams = strParamsBuilder.toString();
Request.Builder builder = new Request.Builder()
.url(url)
.header("accept", "*/*")
.header("connection", "Keep-Alive")
.header("Content-Type", FORM_CONTENT_TYPE)
.post(formBody);
if (headers != null) {
for (Map.Entry<String, String> entry : headers.entrySet()) {
builder.addHeader(entry.getKey(), entry.getValue());
}
}
Request request = builder.build();
try (Response response = HTTP_CLIENT.newCall(request).execute()) {
if (response.isSuccessful()) {
// 处理响应数据
long time = response.receivedResponseAtMillis() - response.sentRequestAtMillis();
String result = response.body() != null ? response.body().string() : null;
printRequestLog(url, FORM_CONTENT_TYPE, strParams, time, result);
return result;
} else {
// 处理错误响应
throw new IOException(String.valueOf(response));
}
} catch (Exception e) {
// 处理网络异常
logger.error("invoke Remote 【POST】 Method exception!== url【{}】,param【{}】", url, strParams);
return returnErrorResult("Remote Request Fail :" + e.getMessage()).toString();
}
}
public static void printRequestLog(
String url, String contentType, String data, Long time, String result) {
// if (StrUtil.isNotBlank(result) && result.length() > 200) {
// result = result.substring(0, 200) + "...";
// }
String log =
"\n================== Remote Request info ==================\n"
+ String.format("Request URL: %s \n", url)
+ String.format("Request Content-Type: %s\n", contentType)
+ String.format("Request Parameter: %s \n", data)
+ String.format("Request Time: %s ms \n", time)
+ String.format("Response Result: %s \n", result)
+ "================== Remote Request info ==================\n";
logger.info(log);
}
public static JSONObject returnErrorResult(String msg) {
JSONObject jsonObject = new JSONObject();
jsonObject.putOpt("code", 1);
jsonObject.putOpt("msg", msg);
jsonObject.putOpt("data", null);
return jsonObject;
}
}
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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# 结论
OkHttp 是一个功能强大且易于使用的 HTTP 客户端,它提供了丰富的功能来满足各种网络请求的需求。无论是简单的 GET 请求还是复杂的文件上传,OkHttp 都能够提供高效的解决方案。通过上述示例,您可以快速地在自己的应用程序中使用 OkHttp 进行网络通信。
# 学习参考
上次更新: 2024/9/25 11:16:13